Jump to content
Sign in to follow this  
Shrinavat

RSA decryption from JavaScript

Recommended Posts

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×