Using RSA-SHA1 with Salesforce Crypto Class
July 6th, 2010
This is a rather obscure post but it will definitely come in handy to someone trying to use the RSA-SHA1 algorithm with the Salesforce Crypto class. I’m spent the past two days trying to hook up OAuth using Apex and various Google Services. The standard HMAC-SHA1 algorithm is fairly straight forward with OAuth and Google but when you are required to register a domain and upload a certificate… well things get somewhat hairy. There’s very little documentation on the RSA-SHA2 algorithm and I could only find one relevant post on the topic.
According to the Crypto docs, the arguments for the sign method are an algorithm name (i.e., RSA-SHA1), an input Blob (the string to encrypt) and a privateKey Blob. The value of privateKey must be decoded using the EncodingUtilbase64Decode method, and should be in RSA’s PKCS #8 (1.2) Private-Key Information Syntax Standard form.
The sample code from the docs doesn’t help determining how to obtain the privateKey:
1 2 3 4 5 | String algorithmName = 'RSA';
String key = 'pkcs8 format private key';
Blob privateKey = EncodingUtil.base64Decode(key);
Blob input = Blob.valueOf('12345qwerty');
Crypto.sign(algorithmName, input, privateKey); |
So after a couple of days of trial and error, swearing and sticking needles in my eyes, I finally came up with the solution for Google. It may not apply to other services but the methodology is roughly the same for the privateKey.
The first step is to generate a self-signing public certificate and private key. You can find more info here. Open terminal and run the following:
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj ‘/C=US/ST=CA/L=San Mateo/CN=www.appirio.com’ -keyout key-mycompanyrsa.pem -out cert-mycompanyrsa.pem
This will spit out a cert file (cert-mycompanyrsa.pem) and private key file (key-mycompanyrsa.pem). Then upload the cert to your domain for the Google account. This will generate a consumer key and a consumer secret for your application.
Now here was my mistake. I was opening the private key file (key-mycompanyrsa.pem) and using the contents of this file in my Apex code for the privateKey Blob value. Google was choking when creating the OAuth request token saying that the signature was incorrect: signature_invalid.
Here’s the fix. You need to use the private key file (key-mycompanyrsa.pem) with the openssl pkcs8 command to process the private keys into PKCS#8 format.
Open terminal again and run:
openssl pkcs8 -topk8 -nocrypt -in key-mycompanyrsa.pem -outform PEM
This will display a new private key in terminal and THIS is the value you use for the privateKey argument for the sign method. Just copy everything betweek the “begin” line and “end” line.
Categories: Apex, Code Sample, Google, Salesforce













public class cryptotest
{
private String getMac(String RequestString, String secretkey) {
String algorithmName = ‘hmacSHA1′; //’RSA’;
Blob input = Blob.valueOf(RequestString);
Blob signing =Crypto.generateMac(algorithmName, input, secretkey);
return EncodingUtil.urlEncode(EncodingUtil.base64Encode(signing), ‘UTF-8′);
//return ”;
}
}
I wrote this litte class in my sandbox and I am getting a very annoying error “Error: Compile Error: Method does not exist or incorrect signature: Crypto.generateMac(String, Blob, String) at line 6 column 23
” can you help ?
Thanks
@AB, check the API version of your class. I may be using an older version and you need to update to 19 or 20.
It’s 20 and same error msg
Hi Jeff,
Very important, the error from salesforce is misleading the third argument is not of type “string” but “Blob” so the solution is :
public class cryptotest
{
private String getMac(String RequestString, String secretkey) {
String algorithmName = ‘hmacSHA1′; //’RSA’;
Blob input = Blob.valueOf(RequestString);
Blob key = Blob.valueOf(secretkey);
Blob signing =Crypto.generateMac(algorithmName, input, key);
return EncodingUtil.urlEncode(EncodingUtil.base64Encode(signing), ‘UTF-8′);
//return ”;
}
}
By the way I am enjoying your blog very much thank you for your sharing passion!I just started my own company and I appreciate your work…see my work at http://www.epowerbilling.com
Hi Jeff,
Thanks for the blogs.
Have you ever tried to encrypte data & put that encrypted data in cookies on one page & try to encrypte that data into other page from cookies in salesforce apex class.
Hi jeff,
i am very surprise to see that why you are doing encryption with private key, can we done this, usually we done encryption with public key and do decryption with private key. Please replay to this comment