2013-05-14 10:05:31 -04:00
|
|
|
/**
|
|
|
|
* A Wrapper for Forge's RSA encryption
|
|
|
|
*/
|
2013-05-16 10:54:56 -04:00
|
|
|
var RSA = function(forge, util) {
|
2013-05-14 10:05:31 -04:00
|
|
|
'use strict';
|
|
|
|
|
2013-05-14 12:48:13 -04:00
|
|
|
var utl = forge.util;
|
|
|
|
|
2013-05-14 14:28:12 -04:00
|
|
|
var keypair = null;
|
2013-05-14 10:05:31 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes the RSA module by passing the user's keypair
|
|
|
|
* The private key is option and required only for decryption
|
|
|
|
* and signing
|
|
|
|
*/
|
2013-05-14 14:28:12 -04:00
|
|
|
this.init = function(pubkeyPem, privkeyPem, keyId) {
|
2013-05-15 06:26:32 -04:00
|
|
|
keypair = {
|
|
|
|
_id: keyId,
|
|
|
|
publicKey: forge.pki.publicKeyFromPem(pubkeyPem)
|
|
|
|
};
|
2013-05-14 10:05:31 -04:00
|
|
|
if (privkeyPem) {
|
2013-05-14 14:28:12 -04:00
|
|
|
keypair.privateKey = forge.pki.privateKeyFromPem(privkeyPem);
|
2013-05-14 10:05:31 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate RSA keypair with the corresponding keysize
|
|
|
|
*/
|
|
|
|
this.generateKeypair = function(keySize, callback) {
|
|
|
|
forge.rsa.generateKeyPair({
|
|
|
|
bits: keySize,
|
2013-05-16 10:54:56 -04:00
|
|
|
workerScript: (typeof app !== 'undefined') ? (app.config.workerPath + '/../../lib/forge/prime.worker.js') : undefined
|
2013-05-14 14:28:12 -04:00
|
|
|
}, function(err, newKeypair) {
|
|
|
|
if (err || !newKeypair || !newKeypair.publicKey || !newKeypair.privateKey) {
|
2013-05-14 10:05:31 -04:00
|
|
|
callback({
|
|
|
|
errMsg: 'RSA keygeneration failed!',
|
|
|
|
err: err
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-05-14 14:28:12 -04:00
|
|
|
keypair = newKeypair;
|
|
|
|
// generate unique keypair ID
|
|
|
|
keypair._id = util.UUID();
|
2013-05-14 10:05:31 -04:00
|
|
|
|
|
|
|
callback();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Exports user's keypair as PEMs
|
|
|
|
*/
|
|
|
|
this.exportKeys = function() {
|
|
|
|
return {
|
2013-05-14 14:28:12 -04:00
|
|
|
_id: keypair._id,
|
|
|
|
pubkeyPem: forge.pki.publicKeyToPem(keypair.publicKey),
|
|
|
|
privkeyPem: forge.pki.privateKeyToPem(keypair.privateKey)
|
2013-05-14 10:05:31 -04:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Encrypt a String using RSA with PKCS#1 v1.5 padding
|
2013-05-14 12:48:13 -04:00
|
|
|
* @param plaintext [String] The input string in UTF-16
|
2013-05-14 10:05:31 -04:00
|
|
|
* @return [String] The base64 encoded ciphertext
|
|
|
|
*/
|
|
|
|
this.encrypt = function(plaintext) {
|
2013-05-14 12:48:13 -04:00
|
|
|
// encode plaintext to utf8 and encrypt
|
2013-05-14 14:28:12 -04:00
|
|
|
var ct = keypair.publicKey.encrypt(utl.encodeUtf8(plaintext));
|
2013-05-14 12:48:13 -04:00
|
|
|
// encode ciphtext to base64
|
|
|
|
return utl.encode64(ct);
|
2013-05-14 10:05:31 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decrypt a String using RSA with PKCS#1 v1.5 padding
|
|
|
|
* @param ciphertext [String] The base64 encoded ciphertext
|
2013-05-14 12:48:13 -04:00
|
|
|
* @return [String] The decrypted plaintext in UTF-16
|
2013-05-14 10:05:31 -04:00
|
|
|
*/
|
|
|
|
this.decrypt = function(ciphertext) {
|
2013-05-14 12:48:13 -04:00
|
|
|
// decode base64 ciphertext to utf8
|
|
|
|
var ctUtf8 = utl.decode64(ciphertext);
|
|
|
|
// decrypt and decode to utf16
|
2013-05-14 14:28:12 -04:00
|
|
|
return utl.decodeUtf8(keypair.privateKey.decrypt(ctUtf8));
|
2013-05-14 10:05:31 -04:00
|
|
|
};
|
|
|
|
|
2013-05-14 12:15:47 -04:00
|
|
|
/**
|
|
|
|
* Signs an Array of Base64 encoded parts with the private key
|
|
|
|
* @param parts [Array] Array of Base64 encoded parts
|
|
|
|
* @return [String] The Base64 encoded signature
|
|
|
|
*/
|
|
|
|
this.sign = function(parts) {
|
2013-05-14 10:05:31 -04:00
|
|
|
var sha = forge.md.sha256.create();
|
2013-05-14 12:15:47 -04:00
|
|
|
parts.forEach(function(i) {
|
2013-05-14 12:52:41 -04:00
|
|
|
// decode base64 part and append to sha msg
|
2013-05-14 12:48:13 -04:00
|
|
|
sha.update(utl.decode64(i));
|
2013-05-14 12:15:47 -04:00
|
|
|
});
|
2013-05-14 10:05:31 -04:00
|
|
|
|
2013-05-14 12:52:41 -04:00
|
|
|
// encode signature to base64
|
2013-05-14 14:28:12 -04:00
|
|
|
return utl.encode64(keypair.privateKey.sign(sha));
|
2013-05-14 10:05:31 -04:00
|
|
|
};
|
|
|
|
|
2013-05-14 12:15:47 -04:00
|
|
|
/**
|
|
|
|
* Verifies an Array of Base64 encoded parts with the public key
|
|
|
|
* @param parts [Array] Array of Base64 encoded parts
|
|
|
|
* @param sig [String] The Base64 encoded signatrure
|
|
|
|
* @return [bool] if the verification was successful
|
|
|
|
*/
|
|
|
|
this.verify = function(parts, sig) {
|
2013-05-14 12:52:41 -04:00
|
|
|
// decode base64 signature to utf8
|
2013-05-14 12:48:13 -04:00
|
|
|
var sigUtf8 = utl.decode64(sig);
|
2013-05-14 10:05:31 -04:00
|
|
|
|
|
|
|
var sha = forge.md.sha256.create();
|
2013-05-14 12:15:47 -04:00
|
|
|
parts.forEach(function(i) {
|
2013-05-14 12:52:41 -04:00
|
|
|
// decode base64 part and append to sha msg
|
2013-05-14 12:48:13 -04:00
|
|
|
sha.update(utl.decode64(i));
|
2013-05-14 12:15:47 -04:00
|
|
|
});
|
2013-05-14 10:05:31 -04:00
|
|
|
|
2013-05-14 14:28:12 -04:00
|
|
|
return keypair.publicKey.verify(sha.digest().getBytes(), sigUtf8);
|
2013-05-14 10:05:31 -04:00
|
|
|
};
|
|
|
|
|
2013-05-16 10:54:56 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
if (typeof module !== 'undefined' && module.exports) {
|
|
|
|
module.exports = RSA;
|
|
|
|
} else {
|
|
|
|
app.crypto.RSA = RSA;
|
|
|
|
}
|