cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
  • Learn how to build custom Python data connectors and further customize JMP’s Data Connector Framework with the Python Data Connector Demo, available now in the JMP Marketplace!
  • See how to create experiments to support product design and ID useful product features. Register for June 12 webinar, 2pm US Eastern Time.

Discussions

Solve problems, and share tips and tricks with other JMP users.
Choose Language Hide Translation Bar
vince_faller
Super User (Alumni)

Encrypting Decrypting with Powershell

I'm trying to encrypt a list of valid JSL using runprogram/powershell.  It's important that this is only a single call to powershell because of performance.  I thought I had it working but realized that single or double quotes messes me up when they're nested lists.  

Also, I can NOT write to a file and have powershell read that.  works great, not allowed to do it though.  I think I'm just broken on the escaping of JSL and C and Powershell. 

 

Names default to here(1);
encryption_key = J(16, 1, randominteger(0, 255));
unencrypted_input = {"Fa'ke\!"", {Empty(), "Str'\!"ing"}}; // this one breaks me
unencrypted_input = {"Fake", {Empty(), "String"}}; // this one is fine

print("encryptng");
init_str = "@("; // creating a powershell array
for(i=1, i<=nitems(unencrypted_input), i++, 
	if(i!=1, init_str ||= ", ");
	item = unencrypted_input[i];
	// for encrypt we want to put it in quotes so we can pull it out later so we can parse;
	if( isstring(item), item = "\!""||char(item)||"\!"");
	// because of the way runprogram works we have to C escape the quotes as well	
	init_str ||= "\\!""||substitute(char(item), "\!"", "'")||"\\!"";
);
init_str ||= ")";

exec_str = init_str || " | ConvertTo-SecureString -AsPlainText -Force"
	|| " | ConvertFrom-SecureString -Key " || Substitute(char(encryption_key), "[", "(", "]", ")");

write("\!n"||exec_str);
rp = Run Program(
	Executable("powershell"), 
	Options(exec_str), 
	ReadFunction("text")
);
print("");
show(rp);

encrypted_list = words(rp, "\!n\!r");

print("decrypting");
// now to decrypt
init_str = "@("; // creating a powershell array
for(i=1, i<=nitems(encrypted_list), i++, 
	if(i!=1, init_str ||= ", ");
	item = encrypted_list[i];
	// because of the way runprogram works we have to C escape the quotes as well	
	init_str ||= "\\!""||substitute(char(item), "\!"", "'")||"\\!"";
);
init_str ||= ")";

exec_str = init_str || " | ConvertTo-SecureString -Key " || Substitute(char(encryption_key), "[", "(", "]", ")")
	|| " | ForEach-Object {"// doing this in a loop in case of multiple lines
	|| "$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($_);"
	|| "[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)}";
	
write("\!n"||exec_str);
rp = Run Program(
	Executable("powershell"), 
	Options(exec_str), 
	ReadFunction("text")
);
print("");
show(rp);
dec_list = Words(rp, "\!n\!r");
for(i=1, i<=nitems(dec_list), i++, 
	r = substitute(dec_list[i], "'", "\!"");
	r = parse(r); // parse it because we wrapped everything
	dec_list[i] = r;
);

show(dec_list, unencrypted_input);
show(dec_list == unencrypted_input);
Vince Faller - Predictum
4 REPLIES 4
vince_faller
Super User (Alumni)

Re: Encrypting Decrypting with Powershell

I think the crux is with going to/from a powershell array.  

 

Maybe this makes things easier to understand

 

 

Names default to here(1);
//unencrypted_input = {"Fa'ke\!"", {Empty(), "Str'\!"ing"}}; // this one breaks me
unencrypted_input = {"Fake", {Empty(), "String"}}; // this one is fine
to_pwsh_array = function({input, wrap_string = 1}, 
	// wrap string because the inputs for decrypt aren't valid JSL so we don't want to wrap those
	{DEFAULT LOCAL}, 
	init_str = "@("; // creating a powershell array
	for(i=1, i<=nitems(input), i++, 
		if(i!=1, init_str ||= ", ");
		item = input[i];
		// for encrypt we want to put it in quotes so we can pull it out later so we can parse;
		if( wrap_string & isstring(item), item = "\!""||char(item)||"\!"");
		// because of the way runprogram works we have to C escape the quotes as well	
		init_str ||= "\\!""||substitute(char(item), "\!"", "'")||"\\!"";
	);
	init_str ||= ")";
);
from_pwsh_array = function({input}, 
	final_list = Words(input, "\!n\!r");
	for(i=1, i<=nitems(final_list), i++, 
		r = substitute(final_list[i], "'", "\!"");
		r = parse(r); // parse it because we wrapped everything
		final_list[i] = r;
	);
	return(final_list);
);

rp = Run Program(
	Executable("powershell"), 
	Options(to_pwsh_array(unencrypted_input)), 
	ReadFunction("text")
);

out = from_pwsh_array(rp);

show(out == unencrypted_input);
Vince Faller - Predictum
ih
Super User (Alumni) ih
Super User (Alumni)

Re: Encrypting Decrypting with Powershell

Could you substitute the quotes in JSL with something that doesn't include a quote and then substitute them back within powershell using replace?

vince_faller
Super User (Alumni)

Re: Encrypting Decrypting with Powershell

I tried to do that with [quote], but I couldn't get it to work because of the the way char(list containing strings) works.  I can't get powershell to give me quotes back, it just strips the quotes, so when I pull it back in (if it has quotes inside as well) then it screws up the parse.  I could maybe make a recursive function with depth so that it goes in and turns all things into what I need then only wrap the top level.  If that makes any sense.  

 

Names default to here(1);
ll = {"Fak'e\!"", {Empty(), "Str'\!"ing"}};
char(ll); // "{\!"Fak'e\!\!\!"\!", {Empty(), \!"Str'\!\!\!"ing\!"}}"

 

 

 

Vince Faller - Predictum
ih
Super User (Alumni) ih
Super User (Alumni)

Re: Encrypting Decrypting with Powershell

I was thinking more like what is below, unless you need to keep the outer list structure in powershell?  I don't think you even need the powershell array unless the encryption function you're using requires it.

Names default to here(1);

to_pwsh_array = function({input, wrap_string = 1}, 
	{DEFAULT LOCAL}, 
	init_str = "@(\\!"" || substitute(char(input),"\!"","[quote]") || "\\!")";
);
from_pwsh_array = function({input}, {default local},
	notrailingnewline = regex(rp,"(.*)\!N","\1");
	replacedquotes = substitute(notrailingnewline, "[quote]", "\!"");
	parsed = parse(replacedquotes);
	parsed;
);

checkvalue = function( {in},
	rp = Run Program(
		Executable("powershell"), 
		Options(to_pwsh_array(in)), 
		ReadFunction("text")
	);
	out = from_pwsh_array(rp);
	show(in, to_pwsh_array(in), rp, out, in == out);
	in != out;
);

if( 
	sum(
		checkvalue( Expr( {"Fake", {Empty(), "String"}} ) ); 
		checkvalue( Expr( {"Fa'ke\!"", {Empty(), "Str'\!"ing"}} ) ); 
	) > 0,
	write("\!N\!NFailed"), 
	write("\!N\!NSuccess")
);

Recommended Articles