In previous post told about setting up grails environment to use bouncycastle lib. Now move to the page side and javascript. After searching around for having a comprehensive, well-documented and simple to use js lib for RSA and AES, I found
pidCrypt interesting (because of the live demo page and simple instruction to use and mainly PEM support, that after going to implement, I found out that is not supported, but I copied the following function from demo page to use it).
function certParser(cert){
var lines = cert.split('\n');
var read = false;
var b64 = false;
var end = false;
var flag = '';
var retObj = {};
retObj.info = '';
retObj.salt = '';
retObj.iv;
retObj.b64 = '';
retObj.aes = false;
retObj.mode = '';
retObj.bits = 0;
for(var i=0; i< lines.length; i++){
flag = lines[i].substr(0,9);
if(i==1 && flag != 'Proc-Type' && flag.indexOf('M') == 0)//unencrypted cert?
b64 = true;
switch(flag){
case '-----BEGI':
read = true;
break;
case 'Proc-Type':
if(read)
retObj.info = lines[i];
break;
case 'DEK-Info:':
if(read){
var tmp = lines[i].split(',');
var dek = tmp[0].split(': ');
var aes = dek[1].split('-');
retObj.aes = (aes[0] == 'AES')?true:false;
retObj.mode = aes[2];
retObj.bits = parseInt(aes[1]);
retObj.salt = tmp[1].substr(0,16);
retObj.iv = tmp[1];
}
break;
case '':
if(read)
b64 = true;
break;
case '-----END ':
if(read){
b64 = false;
read = false;
}
break;
default:
if(read && b64)
retObj.b64 += pidCryptUtil.stripLineFeeds(lines[i]);
}
}
return retObj;
}
On server side, when I tried to decrypt the message I found 2 level bas64 encoding on the message. So first decode as base64 the hash and pass it to doFinal and again decode result as base 64 to have byte [] of the message, then convert to string.
Cipher decryptRSACipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC")
decryptRSACipher.init(Cipher.DECRYPT_MODE, privateKey)
new String(decryptRSACipher.doFinal(hash.decodeBase64()).decodeBase64(), StandardCharsets.UTF_8)
It supposed to be good thing for form submission from javascript side.
The next challenge was decrypting the actual data that encrypted by AES, but the decrypted key in previous by RSA didn't work, so after some research on source and net, another door of knowledge is opened to my eyes. As you may know, it is recommended to use a salt as part of AES key (password), that is fine, but in openssl implementation (that pidCrypt AES follow), the salt is send as part of prefix to the encrypted message (byte 8 to 16), and interesting thing is first 8 bytes are assigned for a "Salted__" string, yes a fixed string. So the message that supposed to be decrypted should be extracted according to the following format.
"Salted__" + 8 Bytes Random Salt + EncryptedMessage
I did some changes to this format to support one time password or expiring the key that will be explained in next post.
This
link may describe openssl AES format better than me.