Android Question RSA encryption / decryption

Johan Schoeman

Expert
Licensed User
Longtime User
While playing around with the PDF417 barcode scanner I thought I would check what info is hiding inside the PDF417 barcode on my driver's license. So, I got the following 720 bytes of hex data from it:

B4X:
HEX = 019b09450000
6713c45dcaf37a7573c2daed9badf4374e3629389f8a6bf3c65104384407f66f3233d4bab833052c89dd15cc80f930691ff8fcc77bf0494ea408b5ec0465a9b88580c95c46cc21349fca03a10b95778cbd9672c53d150e4aae7cbf9b61bdadcd3c69f11033236d2e1227f69f49db401a85a7021a547c616b7038337238d37d10
86bb3c730c737faac164bae9cdaf0273904fa875799078779660f87fbf0a28af53739ac87c39758100fd9bcc3bedc8716c35212b7f911add64c43281bd18eb12f1bc7f01249f14ecf7e6e8ed2e2c66f32f0716aef21b5b7febd889457632caaa878b6d253d5d4f038de565df54b29c8b3dd87714780c0e8c027b1577d9375f76
c2ee868bf2760e27dd2ac4b1611ac2f0695884d2eb80b00c2cd52505a3f3acf58a2306a47172519e67dd3c5ac1e6e49f8535fec93e8d9b322ef9ba2cc5b092ede4a45fa0ba7c014463e860d6faf105ebec9baee6a3255c343a0cc9974b379a7d70b346986688513ef22493fb4d1ae8443cd721827f7eec933891e07f471cc2e1
97c11ea82233d32c666f70802dae71d2bafcec2550f7458d40c23f0c0f3d9452253d9ae6c79bd7d9592fa744c1c3c40b945f48693ca1b447675987ea51d631bed99c63865b25a8446ff2259a454f3707646c27812f175410c930c82c60c3126755650c5d137dcd15b286c32dcccbb3074d667299144df44cc4eb24675e882783
5a581ef384754c2c007d720d82c89c7608cac15437b060f2ef9a97547fca3adbad61da1e9b0db9061fe83c10cf326e92b8b7e787ef8e45ffc056e100a504ae09578fdcedd0d3abf1286c776e7a4bfd02b93f34e9121bf66f17a77a4db36ba04032a553892d1c3f6c377be4f7696357bebaa983ea3166592c8afc35282ae55aba
64d83f7436aa0b4b58670855a28f2e14e67b2e84411e39b7fe19cd68be5ca411b9f60a9f0339e19ae8bda50223fb4930df0b8a20ed4528a601296a814721245db392b6afa929f1d547c3

I have added "HEX = " to the string above. Now apparently the above data is arranged as follows:
1. first 4 bytes - if 01 e1 02 45 then version 1 license else version 2 license (the first 4 bytes in my license are 01 9b 09 45 and therefore it corresponds with version 2) - see here https://stackoverflow.com/questions/17549231/decode-south-african-za-drivers-license
2. The next two bytes are 00 and 00
3. The remainder of the 714 bytes are split into 5 blocks of 128 bytes and 1 block of 74 bytes. The first block of 128 bytes are as follows (and I believe it contains most of the text info - there is apparently image data stored in these blocks as well....):

B4X:
6713c45dcaf37a7573c2daed9badf4374e3629389f8a6bf3c65104384407f66f3233d4bab833052c89dd15cc80f930691ff8fcc77bf0494ea408b5ec0465a9b88580c95c46cc21349fca03a10b95778cbd9672c53d150e4aae7cbf9b61bdadcd3c69f11033236d2e1227f69f49db401a85a7021a547c616b7038337238d37d10

The 5 blocks containing 128 bytes each must be decrypted with RSA decryption making use of the following public key:
B4X:
-----BEGIN RSA PUBLIC KEY-----
MIGWAoGBAMqfGO9sPz+kxaRh/qVKsZQGul7NdG1gonSS3KPXTjtcHTFfexA4MkGA
mwKeu9XeTRFgMMxX99WmyaFvNzuxSlCFI/foCkx0TZCFZjpKFHLXryxWrkG1Bl9+
+gKTvTJ4rWk1RvnxYhm3n/Rxo2NoJM/822Oo7YBZ5rmk8NuJU4HLAhAYcJLaZFTO
sYU+aRX4RmoF
-----END RSA PUBLIC KEY-----

The last block of 74 bytes must also be decrypted making use of RSA decryption but with the following public key:

B4X:
-----BEGIN RSA PUBLIC KEY-----
MF8CSwC0BKDfEdHKz/GhoEjU1XP5U6YsWD10klknVhpteh4rFAQlJq9wtVBUc5Dq
bsdI0w/bga20kODDahmGtASy9fae9dobZj5ZUJEw5wIQMJz+2XGf4qXiDJu0R2U4
Kw==
-----END RSA PUBLIC KEY-----

The only other "tip" that I could find is the following:
Decrypt each block separately. Decrypted with RSA ENCRYPT function using the public key.

Where and how do I start with this in B4A to make sense of the hex code data that I have extracted from my license?
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
The below code comes from here:
https://mybroadband.co.za/vb/showthread.php/382187-Decode-Drivers-Licence-Barcode/page8

How do we translate it to Java?

B4X:
using System;
using System.IO;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Math;

namespace Drivers
{
    class MainClass
    {
        private static byte[] GetPaddedValue (BigInteger value, int length)
        {
            byte[] result = value.ToByteArrayUnsigned();
            byte[] padded = new byte[length];
            Buffer.BlockCopy (result, 0, padded, (length - result.Length), result.Length);
            return padded;
        }

        private static byte[] EncryptValue (byte[] rgb, BigInteger e, BigInteger n, int size)
        {
            BigInteger input = new BigInteger (rgb);
            BigInteger output = input.ModPow (e, n);
            byte[] result = GetPaddedValue (output, size);
            return result;
        }

        public static void Main (string[] args)
        {
            string longKey = @"-----BEGIN RSA PUBLIC KEY-----
MIGWAoGBAMqfGO9sPz+kxaRh/qVKsZQGul7NdG1gonSS3KPXTjtcHTFfexA4MkGA
mwKeu9XeTRFgMMxX99WmyaFvNzuxSlCFI/foCkx0TZCFZjpKFHLXryxWrkG1Bl9+
+gKTvTJ4rWk1RvnxYhm3n/Rxo2NoJM/822Oo7YBZ5rmk8NuJU4HLAhAYcJLaZFTO
sYU+aRX4RmoF
-----END RSA PUBLIC KEY-----";
            
            using (var reader = new StringReader(longKey))
            {
                var pem = new PemReader(reader);
                var o = (RsaKeyParameters)pem.ReadObject();

                var br = new BinaryReader (new FileStream ("myfile", FileMode.Open));

                br.ReadBytes (6);
                byte[] data = br.ReadBytes (128);

                var decrypted = EncryptValue (data, o.Exponent, o.Modulus, 128);
                string base64 = Convert.ToBase64String (decrypted);
                Console.WriteLine ("As base64: " + base64);
            }


        }
    }
}
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
using (var reader = new StringReader(longKey))
{
var pem = new PemReader(reader);
var o = (RsaKeyParameters)pem.ReadObject();
looks like kotlin language?

Anyway; you should have created a new thread for this, also new, question.
 
Upvote 0

monic

Active Member
Licensed User
Longtime User
looks like kotlin language?

Anyway; you should have created a new thread for this, also new, question.

The language is C# quiet similar syntax to java but the framework is very different

B4X:
package Drivers;

import org.BouncyCastle.Crypto.Parameters.*;
import org.BouncyCastle.OpenSsl.*;
import org.BouncyCastle.Math.*;

public class MainClass
{
//Unsigned integer types have no direct equivalent in Java:
    private static byte[] GetPaddedValue(BigInteger value, int length)
    {
//Unsigned integer types have no direct equivalent in Java:
        byte[] result = value.ToByteArrayUnsigned();
//Unsigned integer types have no direct equivalent in Java:
        byte[] padded = new byte[length];
        Buffer.BlockCopy(result, 0, padded, (length - result.length), result.length);
        return padded;
    }

//Unsigned integer types have no direct equivalent in Java:
    private static byte[] EncryptValue(byte[] rgb, BigInteger e, BigInteger n, int size)
    {
        BigInteger input = new BigInteger(rgb);
        BigInteger output = input.ModPow(e, n);
//Unsigned integer types have no direct equivalent in Java:
        byte[] result = GetPaddedValue(output, size);
        return result;
    }

    public static void main(String[] args)
    {
        String longKey = "-----BEGIN RSA PUBLIC KEY-----" + "\r\n" +
"MIGWAoGBAMqfGO9sPz+kxaRh/qVKsZQGul7NdG1gonSS3KPXTjtcHTFfexA4MkGA" + "\r\n" +
"mwKeu9XeTRFgMMxX99WmyaFvNzuxSlCFI/foCkx0TZCFZjpKFHLXryxWrkG1Bl9+" + "\r\n" +
"+gKTvTJ4rWk1RvnxYhm3n/Rxo2NoJM/822Oo7YBZ5rmk8NuJU4HLAhAYcJLaZFTO" + "\r\n" +
"sYU+aRX4RmoF" + "\r\n" +
"-----END RSA PUBLIC KEY-----";

        try (StringReader reader = new StringReader(longKey))
        {
            PemReader pem = new PemReader(reader);
            RsaKeyParameters o = (RsaKeyParameters)pem.ReadObject();
            BinaryReader br = new BinaryReader(new FileStream("myfile", FileMode.Open));
            br.ReadBytes(6);
//Unsigned integer types have no direct equivalent in Java:
            byte[] data = br.ReadBytes(128);

//Unsigned integer types have no direct equivalent in Java:
            byte[] decrypted = EncryptValue(data, o.Exponent, o.Modulus, 128);
            String base64 = Convert.ToBase64String(decrypted);
            System.out.println("As base64: " + base64);
        }


    }
}
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
I know this is an old thread but it is the same issue I am trying to solve. I have put this aside for some time and tackled it again this morning. The following inline Java code seem to do the trick:
B4X:
#If Java

import java.io.StringReader;
import java.math.BigInteger;
import java.security.interfaces.RSAPublicKey;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import java.util.Base64;

public byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}



    //Unsigned integer types have no direct equivalent in Java:
    public byte[] GetPaddedValue(BigInteger value, int length) {
        //Unsigned integer types have no direct equivalent in Java:
        byte[] result = value.toByteArray();
    
if (result[0] == 0) {
    byte[] tmp = new byte[result.length - 1];
    System.arraycopy(result, 1, tmp, 0, tmp.length);
    result = tmp;
}   
    
        //BA.Log("VALUE = " + value);
        String valLength = value.toString();
        //BA.Log("VALUE LENGTH = " + valLength.length());
        //Unsigned integer types have no direct equivalent in Java:
        byte[] padded = new byte[length];
        //BA.Log("PADDED SIZE = " + padded.length);
        //BA.Log("RESULT SIZE = " + result.length);
        //BA.Log("BEFORE COPY");
        System.arraycopy(result, 0, padded, (length - result.length), result.length);
        //BA.Log("AFTER COPY");
        return padded;
    }

    //Unsigned integer types have no direct equivalent in Java:
    public byte[] EncryptValue(byte[] rgb, BigInteger e, BigInteger n, int size) {
        //BA.Log("IN ENCRYPTED");
        BigInteger input = new BigInteger(rgb);
        BigInteger output = input.modPow(e, n);
        //Unsigned integer types have no direct equivalent in Java:
        byte[] result = GetPaddedValue(output, size);
        return result;
    }

    public String tryBollie1(byte[] mybyte) {
        String longKey = "-----BEGIN RSA PUBLIC KEY-----" + "\r\n" +
                         "MIGWAoGBAMqfGO9sPz+kxaRh/qVKsZQGul7NdG1gonSS3KPXTjtcHTFfexA4MkGA" + "\r\n" +
                         "mwKeu9XeTRFgMMxX99WmyaFvNzuxSlCFI/foCkx0TZCFZjpKFHLXryxWrkG1Bl9+" + "\r\n" +
                         "+gKTvTJ4rWk1RvnxYhm3n/Rxo2NoJM/822Oo7YBZ5rmk8NuJU4HLAhAYcJLaZFTO" + "\r\n" +
                         "sYU+aRX4RmoF" + "\r\n" +
                         "-----END RSA PUBLIC KEY-----";
        //BA.Log("lonkKey = " + longKey);   
        String base64 = null;     

        try {
            StringReader reader = new StringReader(longKey);
            //BA.Log("LongKey = " + reader);
            PEMReader pem = new PEMReader(reader);
            //BA.Log("1");
           // RSAKeyParameters o = (RSAKeyParameters)pem.readObject();
 
           RSAPublicKey pubKey = (RSAPublicKey) new PEMReader(reader).readObject();

           RSAKeyParameters o = new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());   
        
            //BA.Log("2");

            //Unsigned integer types have no direct equivalent in Java:
            byte[] data = mybyte;
            //BA.Log("mybyte size = " + mybyte.length);
            //BA.Log("data size = " + data.length);
            //Unsigned integer types have no direct equivalent in Java:
            byte[] decrypted = EncryptValue(data, o.getExponent(), o.getModulus(), 128);
            //BA.Log("3");
            base64 = Base64.getEncoder().encodeToString(decrypted);
        
            //BA.Log("As base64: " + base64);
        
        } catch (Exception e) {
            //BA.Log("RSA decryption error : " + e);
        }
        return base64;
    
    
    }
 
 
    public String tryBollie2(byte[] mybyte) {
        String longKey = "-----BEGIN RSA PUBLIC KEY-----" + "\r\n" +
                         "MF8CSwC0BKDfEdHKz/GhoEjU1XP5U6YsWD10klknVhpteh4rFAQlJq9wtVBUc5Dq" + "\r\n" +
                         "bsdI0w/bga20kODDahmGtASy9fae9dobZj5ZUJEw5wIQMJz+2XGf4qXiDJu0R2U4" + "\r\n" +
                         "Kw==" + "\r\n" +
                         "-----END RSA PUBLIC KEY-----";
        //BA.Log("lonkKey = " + longKey);   
        String base64 = null;     

        try {
            StringReader reader = new StringReader(longKey);
            //BA.Log("LongKey = " + reader);
            PEMReader pem = new PEMReader(reader);
            //BA.Log("1");
           // RSAKeyParameters o = (RSAKeyParameters)pem.readObject();
 
           RSAPublicKey pubKey = (RSAPublicKey) new PEMReader(reader).readObject();

           RSAKeyParameters o = new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());   
        
            //BA.Log("2");

            //Unsigned integer types have no direct equivalent in Java:
            byte[] data = mybyte;
            //BA.Log("mybyte size = " + mybyte.length);
            //BA.Log("data size = " + data.length);
            //Unsigned integer types have no direct equivalent in Java:
            byte[] decrypted = EncryptValue(data, o.getExponent(), o.getModulus(), 128);
            //BA.Log("3");
            base64 = Base64.getEncoder().encodeToString(decrypted);
        
            //BA.Log("As base64: " + base64);
        
        } catch (Exception e) {
            //BA.Log("RSA decryption error : " + e);
        }
        return base64;
    
    
    }


#End If

It requires this Jar:
https://drive.google.com/open?id=1TW_Hv3spE_eoB8Qlr3b7InXfzsG1Qm5h

I am now able to at least extract the following string when scanning the PDF417 code on my driver's license:

B4X:
Decoded block 1: "���7�QA�EB��SCHOEMAN�JH�ZA�ZA�0�0��20220006T6S6�6205045136081������� PBQPWI������C(@��0 ��1E1�#�N�Zʼ��"

I am now trying to run this javascript in a webview (with Webview and WebViewExtras) but if shows nothing:
B4X:
var SALicenseParser = (function () {

  function parse(base64String) {
    var buff = window.atob(base64String);
    var len = buff.length;
    var bytes = new Uint8Array(len);

    for (var i = 0; i < len; i++) {
      bytes[i] = buff.charCodeAt(i);
    }

    var thisLicense = {
      'idNumber': '',
      'idNumberType': '',
      'idCountryOfIssue': '',
      'surname': '',
      'gender': '', // '01' = male, '02' = female
      'initials': '',
      'birthDate': '', // YYYY-MM-DD
      'driverRestrictions': '',  // "00" / "10" / "20" / "12"
      'licenseCountryOfIssue': 'ZA',
      'licenseIssueNumber': '01',
      'licenseNumber': '6234560001AB',
      'licenseValidityStart': '', // YYYY-MM-DD
      'licenseValidityExpiry': '', // YYYY-MM-DD
      'professionalDrivingPermitExpiry': null, // YYYY-MM-DD
      'professionalDrivingPermitCodes': [ // Array of string codes, or null
          //'G',
          //'P'
      ],
      'vehicleLicenses': [
          {
          'code': '',
          'restriction': '',
          'firstIssueDate': '' // YYYY-MM-DD
          }
      ]
    }

    // Header section -- first 10 bytes:
    var headerSection = {
        barcodeVersionNumber: bytes[0],
        stringSectionLength: bytes[5],
        binarySectionLength: bytes[7]
    };

    var stringSectionStartPostion = 10,
      stringSectionLength = bytes[5],
      stringSectionEndPostion = stringSectionStartPostion + stringSectionLength;

    var stringSection = String.fromCharCode.apply(null, bytes.slice(stringSectionStartPostion, stringSectionEndPostion));

    var arr = new Array(),
      i = 0,
      sS = stringSection.length;

      for (; i < sS; i++) {

        if ( stringSection[i].charCodeAt(0) !== 225 && stringSection[i].charCodeAt(0) !== 224 ) {
          if (i === 0) arr[i] = stringSection[i];
          else {
            if (arr[arr.length - 1] === '') {
              arr[arr.length - 1] = stringSection[i];
            }
            else arr[arr.length - 1] += stringSection[i];
          }
        }
        else {
          if ( arr[arr.length - 1] !== '' ) {
//             switch (i) {
//               case 1:
//               case 2:
//               case 6:
//                 if (stringSection[i].charCodeAt(0) === 224) {
//                   arr[arr.length] += ',';
//                 }
//                 break;
//               case 3:
//               default:
                arr[arr.length] = '';
//             }
          }
        }

      }

    thisLicense.vehicleLicenses.code = arr[0];
    thisLicense.surname = arr[1];
    thisLicense.initials = arr[2];
    thisLicense.idCountryOfIssue = arr[3];
    thisLicense.licenseCountryOfIssue = arr[4];
    thisLicense.vehicleLicenses.restriction = arr[5];
    thisLicense.licenseNumber = arr[6];
    thisLicense.idNumber = arr[7];

    return thisLicense;
  }

  return {
    parse: parse
  }

})();

var sampleData = 'Am0WAwAyARaCWkLh4eFTQU5ERVJT4ErhWkHgWkHgMOHh4TYyMzQ1NjAwMDFBQuA4NjA5MTM1MTM5MDEyAiAHAhmqoQoBGYYJEyASERQgFxIUAVdJBAD6AMhDLihAAChCNFWnQrzo0jDnNeVd2987O9NM9v45zkHm/ll7Ivb5cBQx7vfrFr3e975/m97of/HDQKGCh/LRixwt8OqE5KhYXoNDmoVPDQKFWdbMIXtUo8+40zll0RmpShJw785Ys/luDajQ1gRRksEkr7FjiKHRMO4wpyFBGMJfagh7iuNxHOEMJFrGOBpRg5UETHrDTx0mx9RmWuHQjFA+Naa7abq64z0qL5B3ktR5oFuN4rtWXoZeql6MiPthbIY+vGEUN5mPczaChm0UvGwwkQckiCBP+LSAAVexEcEgAKywW4F+62PhksQeG6Zx/0fCjSQUBWD4fEwVwSnz5ARYJAVimcsOERK2EkQ0kXYSqR2NGSxZ9JY1ADb8Y2aC1hQPh/F/NXq+j/IVV3ratkIa1ETAaPu91/FhMgl1MdUWp5yn8UVVm+wFiWW1IC/UsvkUOkKHhSYCaMqt5loAOXGqumWXwtoOK4QcqHboj8RwAqatEPFrOGDu9ChjRI9HpjPpgvTsB3VGApj8Q8RXRPC8zi097mSBVqhNcGcO2vSTKjjIPC5yG+ISRwvFBBnEW9tarAR3lZ98IAMIQgu0VTRca4lsqeIB8xjXXuw1l24bRDiPYi5JEwAlWO09CP+G+6jYdgVLBYskCWGukFDX2g2NLBGjvYB47rCucJ8Yhgjdik1EAgNiKFN3KCCS6qCixBMkBqrbd0FnPWnX3eYFjOWqLbVoEAUARFpF1RRFEBRZS4YgoqogABY7UAEAFFAFVVUBBEVAVVQQAAAAAAAAAAAAAAAA';

function startParsing(event) {
  event.preventDefault();

  var str = document.getElementById('txtBase64String').value.trim();

  if ( str === '' ) return alert('Enter the Base64 String');
 
  document.getElementById('displayParsedJson').textContent =
  JSON.stringify(SALicenseParser.parse(str), true);
  document.getElementById('displayParsedJson').style.display = 'block';
 
}

This is my full B4A code (you need to download the JAR in the link above and copy it to your additional libs folder):

B4X:
#Region  Project Attributes
    #ApplicationLabel: b4aDecrypt
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#AdditionalJar: bcprov-jdk16-1.43
'#AdditionalJar: org-apache-commons-codec

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
 
    Dim nativeMe As JavaObject
    Dim Base64Con As Base64Image

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim su As StringUtils

    Private wv1 As WebView
    Dim WebViewExtras1 As WebViewExtras

End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")
 
    wv1.JavaScriptEnabled = True
    WebViewExtras1.addJavascriptInterface(wv1, "B4A") ' NOT ESSENTIAL
    WebViewExtras1.addWebChromeClient(wv1, "")
    Dim jv As String = File.ReadString(File.DirAssets, "javascript.txt")


    Log("JV = " & jv)
 
    WebViewExtras1.executeJavascript(wv1, jv)
    Sleep(1000)
    Base64Con.Initialize
    nativeMe.InitializeContext
'    nativeMe.RunMethod("makeBollie", Null)

    'This is the HEX string that I generated from the returned scanned PDF417 barcode on my drivers license
'    Dim mystring As String = "019b094500006713c45dcaf37a7573c2daed9badf4374e3629389f8a6bf3c65104384407f66f3233d4bab833052c89dd15cc80f930691ff8fcc77bf0494ea408b5ec0465a9b88580c95c46cc21349fca03a10b95778cbd9672c53d150e4aae7cbf9b61bdadcd3c69f11033236d2e1227f69f49db401a85a7021a547c616b7038337238d37d1086bb3c730c737faac164bae9cdaf0273904fa875799078779660f87fbf0a28af53739ac87c39758100fd9bcc3bedc8716c35212b7f911add64c43281bd18eb12f1bc7f01249f14ecf7e6e8ed2e2c66f32f0716aef21b5b7febd889457632caaa878b6d253d5d4f038de565df54b29c8b3dd87714780c0e8c027b1577d9375f76c2ee868bf2760e27dd2ac4b1611ac2f0695884d2eb80b00c2cd52505a3f3acf58a2306a47172519e67dd3c5ac1e6e49f8535fec93e8d9b322ef9ba2cc5b092ede4a45fa0ba7c014463e860d6faf105ebec9baee6a3255c343a0cc9974b379a7d70b346986688513ef22493fb4d1ae8443cd721827f7eec933891e07f471cc2e197c11ea82233d32c666f70802dae71d2bafcec2550f7458d40c23f0c0f3d9452253d9ae6c79bd7d9592fa744c1c3c40b945f48693ca1b447675987ea51d631bed99c63865b25a8446ff2259a454f3707646c27812f175410c930c82c60c3126755650c5d137dcd15b286c32dcccbb3074d667299144df44cc4eb24675e8827835a581ef384754c2c007d720d82c89c7608cac15437b060f2ef9a97547fca3adbad61da1e9b0db9061fe83c10cf326e92b8b7e787ef8e45ffc056e100a504ae09578fdcedd0d3abf1286c776e7a4bfd02b93f34e9121bf66f17a77a4db36ba04032a553892d1c3f6c377be4f7696357bebaa983ea3166592c8afc35282ae55aba64d83f7436aa0b4b58670855a28f2e14e67b2e84411e39b7fe19cd68be5ca411b9f60a9f0339e19ae8bda50223fb4930df0b8a20ed4528a601296a814721245db392b6afa929f1d547c3"
 
    'This is the above mystring split into 5 blocks of 128 bytes and 1 block of 74 buytes. The first 6 bytes (019b09450000) should be ignored as it only relates to the License Version Number.
    Dim mystring1 As String = "6713c45dcaf37a7573c2daed9badf4374e3629389f8a6bf3c65104384407f66f3233d4bab833052c89dd15cc80f930691ff8fcc77bf0494ea408b5ec0465a9b88580c95c46cc21349fca03a10b95778cbd9672c53d150e4aae7cbf9b61bdadcd3c69f11033236d2e1227f69f49db401a85a7021a547c616b7038337238d37d10"
    Dim mystring2 As String = "86bb3c730c737faac164bae9cdaf0273904fa875799078779660f87fbf0a28af53739ac87c39758100fd9bcc3bedc8716c35212b7f911add64c43281bd18eb12f1bc7f01249f14ecf7e6e8ed2e2c66f32f0716aef21b5b7febd889457632caaa878b6d253d5d4f038de565df54b29c8b3dd87714780c0e8c027b1577d9375f76"
    Dim mystring3 As String = "c2ee868bf2760e27dd2ac4b1611ac2f0695884d2eb80b00c2cd52505a3f3acf58a2306a47172519e67dd3c5ac1e6e49f8535fec93e8d9b322ef9ba2cc5b092ede4a45fa0ba7c014463e860d6faf105ebec9baee6a3255c343a0cc9974b379a7d70b346986688513ef22493fb4d1ae8443cd721827f7eec933891e07f471cc2e1"
    Dim mystring4 As String = "97c11ea82233d32c666f70802dae71d2bafcec2550f7458d40c23f0c0f3d9452253d9ae6c79bd7d9592fa744c1c3c40b945f48693ca1b447675987ea51d631bed99c63865b25a8446ff2259a454f3707646c27812f175410c930c82c60c3126755650c5d137dcd15b286c32dcccbb3074d667299144df44cc4eb24675e882783"
    Dim mystring5 As String = "5a581ef384754c2c007d720d82c89c7608cac15437b060f2ef9a97547fca3adbad61da1e9b0db9061fe83c10cf326e92b8b7e787ef8e45ffc056e100a504ae09578fdcedd0d3abf1286c776e7a4bfd02b93f34e9121bf66f17a77a4db36ba04032a553892d1c3f6c377be4f7696357bebaa983ea3166592c8afc35282ae55aba"
    Dim mystring6 As String = "64d83f7436aa0b4b58670855a28f2e14e67b2e84411e39b7fe19cd68be5ca411b9f60a9f0339e19ae8bda50223fb4930df0b8a20ed4528a601296a814721245db392b6afa929f1d547c3"
 
'    Log("mystring length = " & mystring.Length)
 
    'First Block - 128 bytes
    Dim mybyte(128) As Byte = nativeMe.RunMethod("hexStringToByteArray", Array(mystring1))
    Sleep(0)
'    For i = 0 To mybyte.Length - 1
'        Log("b(" & i & ") = " & mybyte(i))
'    Next
    Sleep(100)
    Dim newbyte(128) As Byte
    For i = 0 To 127
        newbyte(i) = mybyte(i)
    Next
 
    Dim returnedstring As String
    returnedstring = nativeMe.RunMethod("tryBollie1", Array(newbyte))
    Log("returnedstring 1 = " & returnedstring)
 

    Dim MyBase64String As String = returnedstring
    Dim MyBase64StringAsBytes() As Byte = su.DecodeBase64(MyBase64String)
    Dim s As String = BytesToString(MyBase64StringAsBytes, 0, MyBase64StringAsBytes.Length, "UTF8")
    Log( "Decoded block 1: """ & s & """")
    Log(" ")
 
    'Second Block - 128 bytes
    Dim mybyte(128) As Byte = nativeMe.RunMethod("hexStringToByteArray", Array(mystring2))
    Sleep(0)
'    For i = 0 To mybyte.Length - 1
'        Log("b(" & i & ") = " & mybyte(i))
'    Next
    Sleep(100)
    Dim newbyte(128) As Byte
    For i = 0 To 127
        newbyte(i) = mybyte(i)
    Next
 
    Dim returnedstring As String
    returnedstring = nativeMe.RunMethod("tryBollie1", Array(newbyte))
    Log("returnedstring 2 = " & returnedstring)
 

    Dim MyBase64String As String = returnedstring
 

    Dim MyBase64StringAsBytes() As Byte = su.DecodeBase64(MyBase64String)
    Dim s As String = BytesToString(MyBase64StringAsBytes, 0, MyBase64StringAsBytes.Length, "UTF8")
    Log( "Decoded block 2: """ & s & """")
    Log(" ")


 
    'Third Block - 128 bytes
    Dim mybyte(128) As Byte = nativeMe.RunMethod("hexStringToByteArray", Array(mystring3))
    Sleep(0)
'    For i = 0 To mybyte.Length - 1
'        Log("b(" & i & ") = " & mybyte(i))
'    Next
    Sleep(100)
    Dim newbyte(128) As Byte
    For i = 0 To 127
        newbyte(i) = mybyte(i)
    Next
 
    Dim returnedstring As String
    returnedstring = nativeMe.RunMethod("tryBollie1", Array(newbyte))
    Log("returnedstring 3 = " & returnedstring)
 

    Dim MyBase64String As String = returnedstring
    Dim MyBase64StringAsBytes() As Byte = su.DecodeBase64(MyBase64String)
    Dim s As String = BytesToString(MyBase64StringAsBytes, 0, MyBase64StringAsBytes.Length, "UTF8")
    Log( "Decoded block 3: """ & s & """")
    Log(" ")
    
 
    'Fourth Block - 128 bytes
    Dim mybyte(128) As Byte = nativeMe.RunMethod("hexStringToByteArray", Array(mystring4))
    Sleep(0)
'    For i = 0 To mybyte.Length - 1
'        Log("b(" & i & ") = " & mybyte(i))
'    Next
    Sleep(100)
    Dim newbyte(128) As Byte
    For i = 0 To 127
        newbyte(i) = mybyte(i)
    Next
 
    Dim returnedstring As String
    returnedstring = nativeMe.RunMethod("tryBollie1", Array(newbyte))
    Log("returnedstring 4 = " & returnedstring)
 

    Dim MyBase64String As String = returnedstring
    Dim MyBase64StringAsBytes() As Byte = su.DecodeBase64(MyBase64String)
    Dim s As String = BytesToString(MyBase64StringAsBytes, 0, MyBase64StringAsBytes.Length, "UTF8")
    Log( "Decoded block 4: """ & s & """")
    Log(" ")


    'Fifth Block - 128 bytes
    Dim mybyte(128) As Byte = nativeMe.RunMethod("hexStringToByteArray", Array(mystring5))
    Sleep(0)
'    For i = 0 To mybyte.Length - 1
'        Log("b(" & i & ") = " & mybyte(i))
'    Next
    Sleep(100)
    Dim newbyte(128) As Byte
    For i = 0 To 127
        newbyte(i) = mybyte(i)
    Next
 
    Dim returnedstring As String
    returnedstring = nativeMe.RunMethod("tryBollie1", Array(newbyte))
    Log("returnedstring 5 = " & returnedstring)
 

    Dim MyBase64String As String = returnedstring
    Dim MyBase64StringAsBytes() As Byte = su.DecodeBase64(MyBase64String)
    Dim s As String = BytesToString(MyBase64StringAsBytes, 0, MyBase64StringAsBytes.Length, "UTF8")
    Log( "Decoded block 5: """ & s & """")
    Log(" ")


    'Sixth Block - 74 bytes
    Dim mybyte(74) As Byte = nativeMe.RunMethod("hexStringToByteArray", Array(mystring6))
    Sleep(0)
'    For i = 0 To mybyte.Length - 1
'        Log("b(" & i & ") = " & mybyte(i))
'    Next
    Sleep(100)
    Dim newbyte(74) As Byte
    For i = 0 To 73
        newbyte(i) = mybyte(i)
    Next
 
    Dim returnedstring As String
    returnedstring = nativeMe.RunMethod("tryBollie2", Array(newbyte))
    Log("returnedstring 6 = " & returnedstring)
 

    Dim MyBase64String As String = returnedstring
    Dim MyBase64StringAsBytes() As Byte = su.DecodeBase64(MyBase64String)
    Dim s As String = BytesToString(MyBase64StringAsBytes, 0, MyBase64StringAsBytes.Length, "UTF8")
    Log( "Decoded block 6: """ & s & """")
    Log(" ")
 
 
'    Dim mybitmap As Bitmap = Base64Con.DecodeToImage(returnedstring)
'    ImageView1.Bitmap = mybitmap

 

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

#If Java

import java.io.StringReader;
import java.math.BigInteger;
import java.security.interfaces.RSAPublicKey;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import java.util.Base64;

public byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}



    //Unsigned integer types have no direct equivalent in Java:
    public byte[] GetPaddedValue(BigInteger value, int length) {
        //Unsigned integer types have no direct equivalent in Java:
        byte[] result = value.toByteArray();
    
if (result[0] == 0) {
    byte[] tmp = new byte[result.length - 1];
    System.arraycopy(result, 1, tmp, 0, tmp.length);
    result = tmp;
}   
    
        //BA.Log("VALUE = " + value);
        String valLength = value.toString();
        //BA.Log("VALUE LENGTH = " + valLength.length());
        //Unsigned integer types have no direct equivalent in Java:
        byte[] padded = new byte[length];
        //BA.Log("PADDED SIZE = " + padded.length);
        //BA.Log("RESULT SIZE = " + result.length);
        //BA.Log("BEFORE COPY");
        System.arraycopy(result, 0, padded, (length - result.length), result.length);
        //BA.Log("AFTER COPY");
        return padded;
    }

    //Unsigned integer types have no direct equivalent in Java:
    public byte[] EncryptValue(byte[] rgb, BigInteger e, BigInteger n, int size) {
        //BA.Log("IN ENCRYPTED");
        BigInteger input = new BigInteger(rgb);
        BigInteger output = input.modPow(e, n);
        //Unsigned integer types have no direct equivalent in Java:
        byte[] result = GetPaddedValue(output, size);
        return result;
    }

    public String tryBollie1(byte[] mybyte) {
        String longKey = "-----BEGIN RSA PUBLIC KEY-----" + "\r\n" +
                         "MIGWAoGBAMqfGO9sPz+kxaRh/qVKsZQGul7NdG1gonSS3KPXTjtcHTFfexA4MkGA" + "\r\n" +
                         "mwKeu9XeTRFgMMxX99WmyaFvNzuxSlCFI/foCkx0TZCFZjpKFHLXryxWrkG1Bl9+" + "\r\n" +
                         "+gKTvTJ4rWk1RvnxYhm3n/Rxo2NoJM/822Oo7YBZ5rmk8NuJU4HLAhAYcJLaZFTO" + "\r\n" +
                         "sYU+aRX4RmoF" + "\r\n" +
                         "-----END RSA PUBLIC KEY-----";
        //BA.Log("lonkKey = " + longKey);   
        String base64 = null;     

        try {
            StringReader reader = new StringReader(longKey);
            //BA.Log("LongKey = " + reader);
            PEMReader pem = new PEMReader(reader);
            //BA.Log("1");
           // RSAKeyParameters o = (RSAKeyParameters)pem.readObject();
 
           RSAPublicKey pubKey = (RSAPublicKey) new PEMReader(reader).readObject();

           RSAKeyParameters o = new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());   
        
            //BA.Log("2");

            //Unsigned integer types have no direct equivalent in Java:
            byte[] data = mybyte;
            //BA.Log("mybyte size = " + mybyte.length);
            //BA.Log("data size = " + data.length);
            //Unsigned integer types have no direct equivalent in Java:
            byte[] decrypted = EncryptValue(data, o.getExponent(), o.getModulus(), 128);
            //BA.Log("3");
            base64 = Base64.getEncoder().encodeToString(decrypted);
        
            //BA.Log("As base64: " + base64);
        
        } catch (Exception e) {
            //BA.Log("RSA decryption error : " + e);
        }
        return base64;
    
    
    }
 
 
    public String tryBollie2(byte[] mybyte) {
        String longKey = "-----BEGIN RSA PUBLIC KEY-----" + "\r\n" +
                         "MF8CSwC0BKDfEdHKz/GhoEjU1XP5U6YsWD10klknVhpteh4rFAQlJq9wtVBUc5Dq" + "\r\n" +
                         "bsdI0w/bga20kODDahmGtASy9fae9dobZj5ZUJEw5wIQMJz+2XGf4qXiDJu0R2U4" + "\r\n" +
                         "Kw==" + "\r\n" +
                         "-----END RSA PUBLIC KEY-----";
        //BA.Log("lonkKey = " + longKey);   
        String base64 = null;     

        try {
            StringReader reader = new StringReader(longKey);
            //BA.Log("LongKey = " + reader);
            PEMReader pem = new PEMReader(reader);
            //BA.Log("1");
           // RSAKeyParameters o = (RSAKeyParameters)pem.readObject();
 
           RSAPublicKey pubKey = (RSAPublicKey) new PEMReader(reader).readObject();

           RSAKeyParameters o = new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());   
        
            //BA.Log("2");

            //Unsigned integer types have no direct equivalent in Java:
            byte[] data = mybyte;
            //BA.Log("mybyte size = " + mybyte.length);
            //BA.Log("data size = " + data.length);
            //Unsigned integer types have no direct equivalent in Java:
            byte[] decrypted = EncryptValue(data, o.getExponent(), o.getModulus(), 128);
            //BA.Log("3");
            base64 = Base64.getEncoder().encodeToString(decrypted);
        
            //BA.Log("As base64: " + base64);
        
        } catch (Exception e) {
            //BA.Log("RSA decryption error : " + e);
        }
        return base64;
    
    
    }


#End If

Sub wv1_PageFinished (Url As String)
    '   Now that the web page has loaded we can get the page content as a String
    Sleep(0)
    '   see the documentation http://www.b4x.com/forum/additional-libraries-classes-official-updates/12453-webviewextras.html#post70053 for details of the second parameter callUIThread
 
'    Dim Javascript As String
'    Javascript="B4A.CallSub('ProcessHTML', false, document.documentElement.outerHTML)"
 

'    Log("PageFinished: "&Javascript)
'    WebViewExtras1.executeJavascript(wv1, Javascript)
End Sub

Can anyone make sense of executing the java script in a WebView? Am I doing something stupid here with....
B4X:
    wv1.JavaScriptEnabled = True
    WebViewExtras1.addJavascriptInterface(wv1, "B4A") ' NOT ESSENTIAL
    WebViewExtras1.addWebChromeClient(wv1, "")
    Dim jv As String = File.ReadString(File.DirAssets, "javascript.txt")


    Log("JV = " & jv)
 
    WebViewExtras1.executeJavascript(wv1, jv)
 

Attachments

  • javascript.txt
    3.9 KB · Views: 466
  • b4aDecrypt.zip
    13.1 KB · Views: 431
Last edited:
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
Upvote 0

monic

Active Member
Licensed User
Longtime User
I was looking a library from your sample to run the app but couldn't find it. So I guessed that the library must of been updated as Base64Image doesnt exist in Base64Convert v1.10 lastest.

B4X:
'Dim Base64Con As Base64Image
Dim Base64Con As Base64Convert
 
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
I was looking a library from your sample to run the app but couldn't find it. So I guessed that the library must of been updated as Base64Image doesnt exist in Base64Convert v1.10 lastest.

B4X:
'Dim Base64Con As Base64Image
Dim Base64Con As Base64Convert

That's correct @Jamie8763, I've updated the original post, thank you.

I used that library in the following post last weekend whilst reading and writing image data to and from an online database. https://www.b4x.com/android/forum/t...-the-final-result-after-about-1-5-days.96123/
 
Upvote 0
Top