function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
NowshadNowshad 

How to convert the AES-256 key and Initial vector with the public RSA Key(.PEM file) shared by third party system

Problem:-  How to convert the AES-256 key and Initial vector with the public RSA Key (Shared by third party system Agreement Express)
Requirement:-
1. Randomly generate a AES-256 key.
2. Randomly generate an IV.
3. Encrypt the json with the AES key and IV, base64-encode it, and set it as the request
body.
4. Encrypt the AES key with the public RSA key and base64-encode it
5. Encrypt the IV with the public RSA key and base64-encode it
Implementation:
 From the above requirement, I am able to implement the point 1, 2, and 3. Now the technical challenge which we are facing here is, how to convert the AES-256 key and initial vector with the public RSA Key shared by third party system?
Approach one:-
I tried with below code and getting following error System.SecurityException: Invalid Crypto Key”
 Blob encryptedData = Crypto.sign(RSA, AEX-256 Key, AEXThirdPartyPublicKey );
 
Approach two:- Tried below, however client is getting  "java.lang.ArrayIndexOutOfBoundsException: too much data for RSA block"
 
https://gist.github.com/karmats/4270441be5a34fff7062

 
Please let me know if anybody would have came across above scenario. Client shared Public key in .Pem format not the private key.
NowshadNowshad
Approche one  Blob encryptedData = Crypto.sign(‘RSA‘, ‘AEX-256 Key’, ‘AEXThirdPartyPublicKey );
NowshadNowshad
I could able to implement as below:- By using Open SSL use below command to get the module and exponent openssl rsa -pubin -in pubkey.txt -text -noout (Remove (:) from Module ...

https://crypto.stackexchange.com/questions/18031/the-modulus-of-rsa-public-key
NowshadNowshad
  Blob aesKey = Crypto.generateAesKey(256); // Random generated value
        Blob initialVector = Crypto.generateAesKey(128);// Random generated value

 HttpRequest httpRequest = new HttpRequest();  
            httpRequest.setEndPoint(Label.AEX_EndPoint);
         //  httpRequest.setEndPoint('https://requestb.in/zno8xizn');
            httpRequest.setMethod(Constants.Method_Post);  
            httpRequest.setHeader(Constants.Content_Type,Constants.Content_Type_Json);
            httpRequest.setHeader(Constants.Authorization, authorization);
            httpRequest.setHeader(Constants.Key, encryptMyKeys(aesKey));
            httpRequest.setHeader(Constants.Iv, encryptMyKeys(initialVector));
            System.debug('requestJSON @@'+requestJSON);
            httpRequest.setBody(encryptRequest(requestJSON,aesKey,initialVector));
            httpRequest.setTimeout(Constants.Timeout);
            logger = new API_Utils_Logger(httpRequest, Constants.AEX_Publish_Api_Name);
           
NowshadNowshad
public static String encryptRequest(String jsonRequestBody,Blob aesKey, Blob initialVector ) {     
        Blob jsonRequestBodyObject = blob.valueOf(jsonRequestBody);
        Blob encryptedData = Crypto.encrypt(Constants.Advanced_Encryption_Standard, aesKey, initialVector, jsonRequestBodyObject);       
        return EncodingUtil.base64Encode(encryptedData);   
    }   
    
    
    public static String encryptMyKeys(Blob keyValue) {    
     
       String modules = '';
       String exponent = '';
      
       List<EncryptKeys__mdt> moduleList = [select AEX_MODULE_EXPONENT_FROM_PEM_FILE__c from EncryptKeys__mdt where EncryptKeys__mdt.MasterLabel='AEX_MODULE_FROM_PEM_FILE'];
       List<EncryptKeys__mdt> expoentList = [select AEX_MODULE_EXPONENT_FROM_PEM_FILE__c from EncryptKeys__mdt where EncryptKeys__mdt.MasterLabel='AEX_EXPONENT_FROM_PEM_FILE'];
        
        for(EncryptKeys__mdt moduleObject :moduleList){
           modules = moduleObject.AEX_MODULE_EXPONENT_FROM_PEM_FILE__c; 
           break;
        }
        
        for(EncryptKeys__mdt expoentObject:expoentList ){
           exponent = expoentObject.AEX_MODULE_EXPONENT_FROM_PEM_FILE__c;
            break; 
        }
        
        System.debug('modules ## '+modules +' exponent @@ '+exponent );
        
               
        String encModules =  EncodingUtil.base64Encode( EncodingUtil.convertFromHex(modules) ); 
        RsaEncryptionInitialSubmissionApi  rsa = new RsaEncryptionInitialSubmissionApi(encModules ,exponent);
        String  encryptedKey = rsa.encrypt(EncodingUtil.base64Encode(keyValue));
        return encryptedKey ;
    }

 
NowshadNowshad
public with sharing class RsaEncryptionInitialSubmissionApi{

    private String modulus;
    private String exponent;

    // Hex digits
    private static final String DIGITS = '0123456789abcdef';
    private static final Decimal HEX_BASE = 16;

    public RsaEncryptionInitialSubmissionApi(String modulus, String exponent) {
        this.modulus = modulus;
        this.exponent = exponent;
    }

    public String encrypt(String input) {
        Blob mod = EncodingUtil.base64Decode(modulus);
        //Blob exp = EncodingUtil.base64Decode(exponent);
         System.debug('mod size ::'+mod.size());
        // Pad password.nonce
        Blob pn = Blob.valueOf(String.fromCharArray(pkcs1Pad2(input, mod.size()-1)));

        Decimal modDec = hexToDecimal(EncodingUtil.convertToHex(mod));
        Decimal expDec =decimal.valueOf(exponent);// hexToDecimal(EncodingUtil.convertToHex(exp));
        Decimal pnDec = hexToDecimal(EncodingUtil.convertToHex(pn));

        System.debug('modDec :::: '+modDec );
        System.debug('expDec :::: '+expDec );
        
        // Calcluate padded^exp % mod and convert to hex
        Decimal result = modPow(pnDec, expDec, modDec);
        String hexResult = decimalToHex(result);
        // If length is uneven, add an extra 0
        if ((hexResult.length() & 1) == 1) {
            hexResult = '0' + hexResult;
        }

        // Generate the data to be encrypted.
        Blob encodedData = EncodingUtil.convertFromHex(hexResult);
        return EncodingUtil.base64Encode(encodedData);
    }

    @testVisible
    private static Decimal hexToDecimal(String hex) {
        Decimal result = 0;
        integer length = hex.length();
        integer i = 0;
        while(i < length) {
            integer hexByte = DIGITS.indexOf(hex.substring(i, i + 1).toLowerCase());
            i++;
            result += hexByte * HEX_BASE.pow(length - i);
        }
        return result;
    }

    @testVisible
    private static String decimalToHex(Decimal d) {
        String hex = '';
        while (d > 0) {
            Decimal digit = modulus(d, HEX_BASE); // rightmost digit
            hex = DIGITS.substring(digit.intValue(), digit.intValue() + 1) + hex; // string concatenation
            d = d.divide(16, 0, RoundingMode.FLOOR);
        }
        return hex;
    }