just wanted to add that your custom security level suggestions are well thought out.
http://www.jsoftware.com/jwiki/System/Interpreter/Requests07#custom_security_levels ----- Original Message ----- From: Dan Bron <[email protected]> To: J Programming <[email protected]> Cc: Sent: Tuesday, August 11, 2015 11:23 AM Subject: Re: [Jprogramming] unlock.ijs > Btw, the only secret I want to keep safe is the noun 'password' by embedding > it in a locked verb If you’re really concerned about the security of this password, it should not appear in memory in cleartext at all. You should only deal in hashes and comparing hashes. > that is set at run time, Having a user define a verb at runtime is a bit unusual. More typical would be to have them supply the password in a text field, and then creating the verb from that (which you could do automatically, obviously). > pwdcheck =: localvar&('password' [:`(dostuff@[)@.-: ]) Again, where the 8 letters p a s s w o r d coming from? Is someone typing in the full sentence pwdcheck =: localvar&(‘password’ …) into the session manager, manually, every time J is started? (I ask because if that’s *not* the case then you’ve got more points in the workflow where the password could be intercepted, even before the name is locked by 3!:6.) > Does 9!:25 disable the 15!:n commands? Nope. And security level (9!:25) is extremely out of date; I wouldn’t rely on it in general [1]. > Though I don't see a single bit difference in an int there. Yes, that’s what I meant by “requires more pointer chasing” yesterday. I don’t have a complete understanding of the J engine’s memory layout yet, but these structures in turn point to other structures, and somewhere down the chain, there’s a struct A with a flags field (second word) having the VLOCK bit set. It would/will take more investigation to understand how to get from the structures we have in hand to the ultimate structure containing the value of pwdcheck. It’s a SMOP ;) Incidentally, the only differences in the memory dumps you quoted: > 56 0 184 262144 2 1 0 6443034000 6443033120 626935840960 > > 56 0 184 262144 1 1 0 6443034000 6443033120 625002615568 Are in the 5th and final integers. The 5th integer is a reference count. If you delete one of the names pointing to pwdcheck (e.g. erase’pwdcheck’) and call memr again, you’ll see that 2 change to a 1 (or, vice versa, point another name to the 2nd memory structure, and you’ll see its reference count go up). Note that the initial 56 in the original data dumps indicate the “ravel”, “value”, or “data” section of the struct starts after 56 bytes, or seven 8-byte integers (on my 64-bit machine). Therefore everything from 6443034000 6443033120 .. onwards is considered the “value” of this array. I haven’t yet worked out what these initial two values mean, but the third value, the one that differs in the two arrays above, I believe is a pointer to the name (or one of the names?) for the verb. If you do SZI =: IF64 { 4 8 a =: memr (15!:14 <'PWDCHECK'), 0, 1, JINT memr a,(SZI*9),1,JINT 140205391245200 namen =: memr a,(SZI*9),1,JINT memr namen,0,16,JINT 64 0 48 33554432 2 8 1 8 10699157 0 0 7307199678560337928 27491 0 0 7 You’ll see the 4th integer here, type, is 33554432 (2^25), which means “name” [2]. The 8 1 8 bit changes depending on which name you’re inspecting. I originally though the 8 corresponded to the 8 characters in ‘pwdcheck’, but on further investigation that turned out to be a red herring (then I thought maybe the 8 was an index into the global symbol table, but 8 seems suspiciously low for a name created so late in the J session). The subsequent six values in the original arrays, > 0 0 0 9223372036854775807 9223372036854775807 9223372036854775807 have been the same in all verbs I’ve inspected so far, and look like sentinels to me (3 3 # 0, 2^64-1): three pairs of mins and maxes? Finally, if you read a little further into memory, you’ll find several more pointers until you hit the next entry in table (i.e. the next series of bytes which follow the same pattern as the two arrays quoted above). It may be in these pointers that the value of the verb pwdcheck is hidden. All we know is it’s there somewhere, and therefore with enough effort we can expose it. > I guess even if it did, external processes can read memory. Yes, this is what I meant with my advice that 3!:6 is merely an encoding, not true encryption. I promise you the string ‘password’ appears *somewhere* in the J process’ memory (else -: couldn’t match against it). The advantage we have from doing this inside of J is we have a handle on where to start (i.e. with 15!:6), but in theory a process with access to J’s memory (if not protected by the OS and/or hardware exceptions) could just scan the whole thing looking, seriatim, for likely strings. Even if 15!:6 were taken away from us in J completely, we could simulate this memory-scanning starting from square one with 15!:0 (call external library, likely OS APIs). All I want to drive home is that this security model is breakable. Certainly using 3!:6 makes it *harder* to access your sensitive data, and that’s a good thing, but it should not lull you into a false sense of perfect, or even particularly high, security. -Dan [1] security level out of date http://www.jsoftware.com/jwiki/System/Interpreter/Bugs#security_level_out_of_date <http://www.jsoftware.com/jwiki/System/Interpreter/Bugs#security_level_out_of_date> [2] Interpretations of struct A’s “type” field: https://github.com/openj/core/blob/18fd23bbdc2f50770eb3047e978cd5e4e3b47039/jtype.h#L123 <https://github.com/openj/core/blob/18fd23bbdc2f50770eb3047e978cd5e4e3b47039/jtype.h#L123> ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
