Shrinavat 17 Posted Monday at 01:28 PM Hey everyone, I’m trying to reverse engineer a piece of JavaScript code found within an HTML file. It has this get_cookie_spsc_encrypted_part function, which contains an RSA private key embedded within a comment, and also an encrypted string. It uses some JavaScript crypto lib, KJUR.crypto.Cipher.decrypt, to decrypt this string. Here’s the Javascript code: function get_cookie_spsc_encrypted_part() { let func = function () {/*-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDFoP5AJIv1KFGRpv/Uw7drFXjWbZG6wNsO7P58ocZIcxyKGU6u TgXw8N1IvTmd9yXRSdcb2fCWB7J/QUQDJQ3YuuXSOQCVOdi8Wy9UoZ5jNdqtZ6CM CvnK/v4Wy38ZhrB0CRkeiuyjmUdfQhe8mh3pE3iFBusYd1TVCxQt3VBkqQIDAQAB AoGAaYBaeo+ID6YodWL7a+/XeNkLmxz/EP1nc/5clNgf7AlXkPmVoUORtGBBIVWy 7ntDuwh6Ryn/X3hYd8q1riAX1UwVuUduOENmgyzmO1rRIoB/17vzYwVMYOB2h+qb xEqjg4dUfk/1occyDwpehWel+1NIgvQLNYLcn2JXxkAyrMkCQQD37+3Y8sjYxwAp giIClsCjrla73cS/QwzArGEnOjBs86LyzCc0pNzmP2OD0a9VlD3k6dMnhT2Oj+2k nZs8dUlHAkEAzA4/mQeFvdiKIkzUBECn3w9Ylu2IfpKnQt/0EFUENxS9ONZ1jj4p zDBfZosgwnE1GiECELM3R/6Pzl+uIGrajwJBALm5HG3az+CykMiHFnrh+kOiII5x vSOYUkEx30THLecvSeyeSPACXwaKjTz9IV31wbdsACQmhsn3vogFF3feU5kCQARP 9MYeI5RshBbPeteQKjwLjfq6kFzkaoZ+RyElOs6TMKCH37oe1DFNgGahYBLb45xm wC1sLCnoVk+tM/fZaj8CQGQyIlxwbgNBBdV3wnmtX9yPDflOsjpo3FuBMOu3nZAD KEpmTXFgdwP4oMMbCmDvH3dav92LE5JN1cPik9z0Piw= -----END RSA PRIVATE KEY----- */}; let pem = func.toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1]; return KJUR.crypto.Cipher.decrypt("82a4fa1da959701407ae4a80b48c0dca57d68fb5e54df1794418b03ba43ef9022328e4be4011ffbeb74d9d22769634a21537ba32788342f8abe6cfddc22512a39373ea2488af389740ac4f93699da92fcd86895c64bd6760a5aea27e172052947361177f3674ec68c52480744a75163c892556ec526387c92c0b50ab0b3a4ea5", KEYUTIL.getKey(pem)); } I’ve managed to replicate the decryption in C# using System.Security.Cryptography. Here’s the C# code: using System.Text.RegularExpressions; using System.Security.Cryptography; var pemKey = Regex.Match(html, "-----BEGIN RSA PRIVATE KEY-----[\\s\\S]*?-----END RSA PRIVATE KEY-----").Value; var encryptedDataHex = Regex.Match(html, @"KJUR.crypto.Cipher.decrypt\(""(.*)""").Groups[1].Value; using var rsa = RSA.Create(); rsa.ImportFromPem(pemKey); var decryptedData = rsa.Decrypt(Convert.FromHexString(encryptedDataHex), RSAEncryptionPadding.Pkcs1); // Perform Decryption Now, I’m trying to do the same in Delphi, and I’d like to use TurboPower LockBox 3. Unfortunately, the official documentation seems to be offline. I am struggling to understand how to use LockBox 3, or other suitable free libraries for this purpose. Could anyone provide some Delphi code examples and guidance on how to do the RSA decryption, using LockBox or any other free library? Any help would be greatly appreciated! Here's my code: program RSA_test; {$APPTYPE CONSOLE} uses System.SysUtils, System.Classes, System.RegularExpressions, uTPLb_Codec, uTPLb_CryptographicLibrary, uTPLb_BaseNonVisualComponent, uTPLb_Signatory, uTPLb_Constants, uTPLb_Asymetric, uTPLb_RSA_Engine, uTPLb_OpenSSL; const HTML = '<html><head><script>function get_cookie_spsc_encrypted_part() {' + ' let func = function () {/*-----BEGIN RSA PRIVATE KEY-----' + 'MIICXAIBAAKBgQDFoP5AJIv1KFGRpv/Uw7drFXjWbZG6wNsO7P58ocZIcxyKGU6u' + 'TgXw8N1IvTmd9yXRSdcb2fCWB7J/QUQDJQ3YuuXSOQCVOdi8Wy9UoZ5jNdqtZ6CM' + 'CvnK/v4Wy38ZhrB0CRkeiuyjmUdfQhe8mh3pE3iFBusYd1TVCxQt3VBkqQIDAQAB' + 'AoGAaYBaeo+ID6YodWL7a+/XeNkLmxz/EP1nc/5clNgf7AlXkPmVoUORtGBBIVWy' + '7ntDuwh6Ryn/X3hYd8q1riAX1UwVuUduOENmgyzmO1rRIoB/17vzYwVMYOB2h+qb' + 'xEqjg4dUfk/1occyDwpehWel+1NIgvQLNYLcn2JXxkAyrMkCQQD37+3Y8sjYxwAp' + 'giIClsCjrla73cS/QwzArGEnOjBs86LyzCc0pNzmP2OD0a9VlD3k6dMnhT2Oj+2k' + 'nZs8dUlHAkEAzA4/mQeFvdiKIkzUBECn3w9Ylu2IfpKnQt/0EFUENxS9ONZ1jj4p' + 'zDBfZosgwnE1GiECELM3R/6Pzl+uIGrajwJBALm5HG3az+CykMiHFnrh+kOiII5x' + 'vSOYUkEx30THLecvSeyeSPACXwaKjTz9IV31wbdsACQmhsn3vogFF3feU5kCQARP' + '9MYeI5RshBbPeteQKjwLjfq6kFzkaoZ+RyElOs6TMKCH37oe1DFNgGahYBLb45xm' + 'wC1sLCnoVk+tM/fZaj8CQGQyIlxwbgNBBdV3wnmtX9yPDflOsjpo3FuBMOu3nZAD' + 'KEpmTXFgdwP4oMMbCmDvH3dav92LE5JN1cPik9z0Piw=' + '-----END RSA PRIVATE KEY-----' + '*/};' + ' let pem = func.toString().match(/[^]*\\/\\*([^]*)\\*\\/\\}$/)[1];' + ' return KJUR.crypto.Cipher.decrypt("82a4fa1da959701407ae4a80b48c0dca57d68fb5e54df1794418b03ba43ef9022328e4be4011ffbeb74d9d22769634a21537ba32788342f8abe6cfddc22512a39373ea2488af389740ac4f93699da92fcd86895c64bd6760a5aea27e172052947361177f3674ec68c52480744a75163c892556ec526387c92c0b50ab0b3a4ea5", KEYUTIL.getKey(pem));' + '} </script></head><body></body></html>'; var PEMKey, EncryptedDataHex, DecryptedData: string; Codec: TCodec; CryptoLib: TCryptographicLibrary; Signatory: TSignatory; EncryptedBytes, DecryptedBytes: TBytes; MemStream: TMemoryStream; StringStream: TStringStream; begin try Codec := TCodec.Create(nil); CryptoLib := TCryptographicLibrary.Create(nil); Signatory := TSignatory.Create(nil); try with TRegEx.Match(HTML, '-----BEGIN RSA PRIVATE KEY-----[\s\S]*?-----END RSA PRIVATE KEY-----') do if Success then PEMKey := Value; with TRegEx.Match(HTML, 'KJUR\.crypto\.Cipher\.decrypt\("(.*)\"') do if Success then EncryptedDataHex := Groups[1].Value; // Convert base64-string to bytes EncryptedBytes := TNetEncoding.Base64.DecodeStringToBytes(EncryptedDataHex); // Setup encryption components Codec.CryptoLibrary := CryptoLib; Codec.StreamCipherId := 'native.RSA'; Codec.ChainModeId := 'native.CBC'; Codec.AsymetricKeySizeInBits := 1024; // ??? StringStream := TStringStream.Create(PEMKey); try Signatory.Codec := Codec; Signatory.LoadKeysFromStream(StringStream, [partPrivate]); // !!! raised exception class EReadError with message 'Stream read error' finally StringStream.Free; end; // Decrypt data MemStream := TMemoryStream.Create; try MemStream.WriteBuffer(EncryptedBytes[0], Length(EncryptedBytes)); MemStream.Position := 0; Codec.DecryptStream(MemStream, MemStream); // In-place decryption // Get decrypted data SetLength(DecryptedBytes, MemStream.Size); MemStream.Position := 0; MemStream.ReadBuffer(DecryptedBytes[0], MemStream.Size); DecryptedData := TEncoding.UTF8.GetString(DecryptedBytes); finally MemStream.Free; end; finally Codec.Free; CryptoLib.Free; Signatory.Free; end; except on E: Exception do WriteLn(E.ClassName, ': ', E.Message); end; ReadLn; end. Share this post Link to post
Kas Ob. 124 Posted yesterday at 07:48 AM Hi, I waited for someone else to add an answer for you as i don't use LockBox, and have no experience with it, sources i looked at https://github.com/TurboPack/LockBox https://github.com/TurboPack/LockBox3 Now to what i see (without building or compiling anything): 1) Extracted the private key from your post and pasted it on ASN1 decoder and here the result https://lapo.it/asn1js/#MIICXAIBAAKBgQDFoP5AJIv1KFGRpv_Uw7drFXjWbZG6wNsO7P58ocZIcxyKGU6uTgXw8N1IvTmd9yXRSdcb2fCWB7J_QUQDJQ3YuuXSOQCVOdi8Wy9UoZ5jNdqtZ6CMCvnK_v4Wy38ZhrB0CRkeiuyjmUdfQhe8mh3pE3iFBusYd1TVCxQt3VBkqQIDAQABAoGAaYBaeo-ID6YodWL7a-_XeNkLmxz_EP1nc_5clNgf7AlXkPmVoUORtGBBIVWy7ntDuwh6Ryn_X3hYd8q1riAX1UwVuUduOENmgyzmO1rRIoB_17vzYwVMYOB2h-qbxEqjg4dUfk_1occyDwpehWel-1NIgvQLNYLcn2JXxkAyrMkCQQD37-3Y8sjYxwApgiIClsCjrla73cS_QwzArGEnOjBs86LyzCc0pNzmP2OD0a9VlD3k6dMnhT2Oj-2knZs8dUlHAkEAzA4_mQeFvdiKIkzUBECn3w9Ylu2IfpKnQt_0EFUENxS9ONZ1jj4pzDBfZosgwnE1GiECELM3R_6Pzl-uIGrajwJBALm5HG3az-CykMiHFnrh-kOiII5xvSOYUkEx30THLecvSeyeSPACXwaKjTz9IV31wbdsACQmhsn3vogFF3feU5kCQARP9MYeI5RshBbPeteQKjwLjfq6kFzkaoZ-RyElOs6TMKCH37oe1DFNgGahYBLb45xmwC1sLCnoVk-tM_fZaj8CQGQyIlxwbgNBBdV3wnmtX9yPDflOsjpo3FuBMOu3nZADKEpmTXFgdwP4oMMbCmDvH3dav92LE5JN1cPik9z0Piw And that is correct and valid RSA key, yet clicked and browsed the sources on github, there is no ASN1 decoder in the sources, the closest thing is using OpenSSL to do the loading of the private key, or to be more accurate to decode the private key to usable format by TP. 2) searching for KJUR.crypto.Cipher.decrypt, found this https://kjur.github.io/jsrsasign/api/symbols/KJUR.crypto.Cipher.html So the encryption indeed is RSAOAEP, (RSA encryption is completely different from RSAOAEP for future references don't mix them), also check the sources and its look like TP can do RSAOAEP https://github.com/TurboPack/LockBox3/blob/master/run/RSA/uTPLb_RSA_Primitives.pas#L116 And that what you should use, so your code is using "Signatory: TSignatory" in complete wrong path 3) Also important the JS code does the decryption, and as usual decryption parameters way less than encryption, to perform RSAOAEP encryption and decryption sometimes you need the default parameters and sometimes you need to figure if there is some default must be set before the decryption. 3) Couldn't find useful examples for you but, so others may help here, or you can start by looking at https://github.com/TurboPack/LockBox3/blob/master/test/uLockBox_RSA_TestCases.pas#L466 Notice there codec and no TSignatory, but the most important (for me at least) these keys are not decodable as they are not ASN1, from the sources they look like custom format specific to LockBox Here SO question, close enough to your problem https://stackoverflow.com/questions/68186850/lockbox-3-encrypt-rsa-with-public-certyficate Again couldn't find what can solve your problem in full Suggestion With above i hope you have better understanding what is your problem actually is, it is loading the private key as first step, then perform the right decryption with RSAOAEP, and that is it, so either try with OpenSSL to load and decrypt or look for different library. And good luck ! 2 1 Share this post Link to post
Shrinavat 17 Posted 13 hours ago Hi Kas Ob., Thank you so much for your detailed response and for taking the time to look into this. I really appreciate your help and insights! You're right, the main issue was loading the private key correctly, as TurboPower LockBox 3 doesn't seem to have built-in ASN.1 decoding capabilities. After considering your suggestions, I decided to switch from TurboPower LockBox 3 and use an OpenSSL wrapper instead, along with libeay32.dll. This approach allows me to properly handle the PEM-encoded private key and perform the RSA decryption. I've managed to get it working, and it seems to be decrypting the string as expected. For anyone interested, I've attached a zip file with a sample project demonstrating the solution. Please note that the code is still a bit rough around the edges and could use some cleaning up. Thanks again for your guidance! src.zip 1 Share this post Link to post