1. Eric Nieva
  2. PowerBuilder
  3. Monday, 5 October 2020 00:51 AM UTC

I am trying to generate the payload for a rest API and part of the payload is a digital signature using our private key.
The private key is generated from an external source using openssl, with AES-256 encryption as below:

openssl genrsa -aes256 -passout pass:{password} -out {location} 2048

and then converted to PKCS#8 format also using openssl.

I am using the CrypterObject AsymmetricSign function to generate the signature using the PKCS#8 private key but I get an Invalid privKey error.

Does PB2019 support encrypted private keys for AsymmetricSign? If so, are there additional steps that need to be done before I call this function?

Thanks,

Eric

 

Below is the sample code:

String ls_private_key_pkcs8
Blob lblb_private_key, lblb_hash, lblb_sign

CrypterObject lnv_CrypterObject
CoderObject lnv_CoderObject

lnv_CrypterObject = Create CrypterObject
lnv_CoderObject = Create CoderObject

ls_private_key_pkcs8 = 'MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI77MkcuVWINQCAggA'
ls_private_key_pkcs8 += 'MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBD3UscJJMjByZaOQnhrEXF1BIIE'
ls_private_key_pkcs8 += '0LygIgD3de0dMf9zvPnaNEMG2JNZow42DQjN7EOo+ni4blH+AgYB1jWzH+1BWkQn'


lblb_private_key = lnv_CoderObject.Base64Decode(ls_private_key_pkcs8)

lblb_hash = lnv_CrypterObject.SHA(SHA256!, Blob('Key=Value', EncodingUTF8!))

lblb_sign = lnv_CrypterObject.AsymmetricSign(RSA!, lblb_hash, lblb_private_key)

 

Bruce Armstrong Accepted Answer Pending Moderation
  1. Tuesday, 6 October 2020 18:18 PM UTC
  2. PowerBuilder
  3. # 1

You need to decrypt that key before converting it to PKCS#8.

PKCS#8 is a Base64 encoded format, so you then need to do the base64 decode on the key before giving it to the PowerBuilder function.

PowerBuilder doesn't have any way to use an encrypted key.  At least not yet.  That's something you might want to recommend to them.

Comment
  1. Bruce Armstrong
  2. Monday, 2 November 2020 16:02 PM UTC
I've written a C# assembly that takes a Base64 encoded value that has been SHA-256 hashed and a string that is the private key in either PKCS 1 or PKCS 8 format and returns a Base64UrlEncoded signed value. It works fine when I unit test it, but when I import it into PowerBuilder and use it I get a runtime error. Still debugging that.



The code is fairly simple:



public string SignData(string hashedData, string privateKey)

{

// The array to store the signed message in bytes

byte[] originalData;

byte[] signedBytes;

int bytesRead;



//Convert hashedData in Base64 to byte array

originalData = Convert.FromBase64String(hashedData);



using (var rsa = RSA.Create())

{

// Import the private key used for signing the message

bool isPkcsprivateKey = privateKey.Contains("BEGIN PRIVATE KEY");

if (isPkcsprivateKey)

{

privateKey = privateKey.Replace("-----BEGIN PRIVATE KEY-----", string.Empty).Replace("-----END PRIVATE KEY-----", string.Empty);

privateKey = privateKey.Replace(Environment.NewLine, string.Empty);

var privateKeyBytes = Convert.FromBase64String(privateKey);

rsa.ImportPkcs8PrivateKey(privateKeyBytes, out bytesRead);

}

else

{

privateKey = privateKey.Replace("-----BEGIN RSA PRIVATE KEY-----", string.Empty).Replace("-----END RSA PRIVATE KEY-----", string.Empty);

privateKey = privateKey.Replace(Environment.NewLine, string.Empty);

var privateKeyBytes = Convert.FromBase64String(privateKey);

rsa.ImportRSAPrivateKey(privateKeyBytes, out bytesRead);

}

// Sign the hashed data

signedBytes = rsa.SignHash(originalData, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

}

// Convert the byte array to a base64url string before returning

return Convert.ToBase64String(signedBytes)

.Replace('+', '-') // replace URL unsafe characters with safe ones

.Replace('/', '_') // replace URL unsafe characters with safe ones

.Replace("=", ""); // no padding

}

}

  1. Helpful
  1. Bruce Armstrong
  2. Tuesday, 3 November 2020 07:46 AM UTC
I came up with another one that uses Bouncy Castle and does the job. This one takes in the raw data to be signed and does both the SHA256 hashing and the RSA signature. It takes the PCKS8 string in PEM format.



public string RS256 (string unsignedData, string privateKey)

{

byte[] msgBytes = Encoding.UTF8.GetBytes(unsignedData);

ISigner signer = SignerUtilities.GetSigner(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id);

privateKey = privateKey.Replace("-----BEGIN RSA PRIVATE KEY-----", string.Empty).Replace("-----END RSA PRIVATE KEY-----", string.Empty);

privateKey = privateKey.Replace(Environment.NewLine, string.Empty);

byte[] privateKeyBytes = Convert.FromBase64String(privateKey);

var privKeyObj = Asn1Object.FromByteArray(privateKeyBytes);

var privStruct = RsaPrivateKeyStructure.GetInstance((Asn1Sequence)privKeyObj);

signer.Init(true, new RsaKeyParameters(true, privStruct.Modulus, privStruct.PrivateExponent));

signer.BlockUpdate(msgBytes, 0, msgBytes.Length);

byte[] sigBytes = signer.GenerateSignature();

return Convert.ToBase64String(sigBytes)

.Replace('+', '-') // replace URL unsafe characters with safe ones

.Replace('/', '_') // replace URL unsafe characters with safe ones

.Replace("=", ""); // no padding

}



I'll post it up in the CodeXchange section sometime tomorrow. You just run the .Net DLL importer on the assembly, pass in the data and your private key and you'll get the base64urlencoded signature data out.



I'm doing base64urlencodd because I'm using it for JWT. What format are you looking for?
  1. Helpful
  1. Bruce Armstrong
  2. Wednesday, 4 November 2020 04:30 AM UTC
I did a bit more work on it so that it supports both PKCS#1 and PKCS#8 keys. I also have it returning the result in just plain Base64 format:



https://community.appeon.com/index.php/codeexchange/powerbuilder/266-rs256-encryption-using-bouncy-castle-through-net-assembly-import
  1. Helpful
There are no comments made yet.
Bruce Armstrong Accepted Answer Pending Moderation
  1. Monday, 5 October 2020 01:03 AM UTC
  2. PowerBuilder
  3. # 2

 

Decrypt the private key using AES128 first, and then pass that to the AsymmetricSign method.

Comment
  1. Eric Nieva
  2. Tuesday, 6 October 2020 09:19 AM UTC
Thanks, Bruce. However I just found out that the openssl command we had to use to convert the private key to pkcs#8,

openssl pkcs8 -topk8 -in {encrypted private key file} -out {pkcs8 encrypted private key file}

converts the private key to PKCS#8 format using AES with 256 bit key and hmacWithSHA256.

How should I go about to decrypt this? The SymmetricDecrypt function only has the algorithm (AES256) as parameter.



Also another noob question, do I decrypt the key BEFORE or AFTER i base64 decode the key?



Thanks!
  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.