UNPKG

authorify-client

Version:

Client for Authorify authorization and authentication system for REST server

255 lines (251 loc) 8.06 kB
/** * A mixin class with encryption features. * * @class node_modules.authorify_client.mixin.WithCrypto * @inheritable * * @author Marcello Gesmundo * * # License * * Copyright (c) 2012-2014 Yoovant by Marcello Gesmundo. All rights reserved. * * This program is released under a GNU Affero General Public License version 3 or above, which in summary means: * * - You __can use__ this program for __no cost__. * - You __can use__ this program for __both personal and commercial reasons__. * - You __do not have to share your own program's code__ which uses this program. * - You __have to share modifications__ (e.g bug-fixes) you've made to this program. * * For more convoluted language, see the LICENSE file. * */ module.exports = function(app) { 'use strict'; var forge = app.config.crypto, base64url = app.base64url, Class = app.jsface.Class, errors = app.errors, pki = forge.pki, caStore = pki.createCaStore(), SCHEME = 'RSA-OAEP', MODE = 'CTR'; var CError = errors.InternalError; return Class({ $statics: { /** * Get bytes from a secret key * * @param {String} secret The secret in Base64 format * @return {Bytes} The secret bytes * @static * @private */ getBytesFromSecret: function(secret) { var keyIv; if (!secret) { throw new CError('missing secret').log(); } // secret is a Base64 string if(secret.isBase64()){ try { keyIv = forge.util.decode64(secret); } catch (e) { throw new CError('secret not valid').log(); } } else { keyIv = secret; } return keyIv; }, /** * Generate a new secret key * * @return {String} The secret in Base64 format * @static */ generateSecret: function() { return forge.util.encode64(forge.random.getBytesSync(16)); } }, /** * Set the private RSA key * @param {String} pem The private RSA key in pem format */ setKey: function(pem) { if (pem) { this._key = pki.privateKeyFromPem(pem); } }, /** * Get the private RSA key in native format * @return {String} The private RSA key */ getKey: function() { return this._key; }, /** * Get the private RSA key in pem format * @return {String} The private RSA key */ getKeyPem: function() { return pki.privateKeyToPem(this._key).newLineSanify(); }, /** * Set the X.509 certificate * @param {String} pem The X.509 certificate in pem format */ setCert: function(pem) { if (pem) { this._cert = pki.certificateFromPem(pem); } }, /** * Get the X.509 certificate in native format * @return {String} The X.509 certificate */ getCert: function() { return this._cert; }, /** * Get the X.509 certificate in pem format * @return {String} The X.509 certificate */ getCertPem: function() { return pki.certificateToPem(this._cert).newLineSanify(); }, /** * Set the CA certificate * @param {String} pem The CA certificate in pem format */ setCa: function(pem) { if (pem) { this._ca = pki.certificateFromPem(pem); caStore.addCertificate(this._ca); } }, /** * Get the CA certificate in native format * @return {String} The CA certificate */ getCa: function() { return this._ca; }, /** * Get the CA certificate in pem format * @return {String} The CA certificate */ getCaPem: function() { return pki.certificateToPem(this._ca).newLineSanify(); }, /** * Encrypt data using RSA public key inside the X.509 certificate * @param {String} data The data to encrypt * @param {String} [scheme='RSA-OAEP'] The scheme to be used in encryption. * Use 'RSAES-PKCS1-V1_5' in legacy applications. * @return {String} The RSA encryption result in Base64 */ encryptRsa: function (data, scheme) { // scheme = RSA-OAEP, RSAES-PKCS1-V1_5 scheme = scheme || SCHEME; return forge.util.encode64(this._cert.publicKey.encrypt(data, scheme)); }, /** * Decrypt RSA encrypted data * @param {String} data The data to decrypt * @param {String} [scheme='RSA-OAEP'] The mode to use in decryption. 'RSA-OAEP', 'RSAES-PKCS1-V1_5' are allowed schemes. * @return {String} The decrypted data */ decryptRsa: function (data, scheme) { scheme = scheme || SCHEME; return this._key.decrypt(forge.util.decode64(data), scheme); }, /** * Encrypt data using AES cipher * @param {String} data The data to encrypt * @param {Bytes} secret The secret to use in encryption * @param {String} [encoder = 'base64'] base64 or url final encoding * @param {String} [mode = 'CTR'] The mode to use in encryption. 'CBC', 'CFB', 'OFB', 'CTR' are allowed modes. * @return {String} The AES encryption result in Base64 */ encryptAes: function (data, secret, encoder, mode) { // mode = CBC, CFB, OFB, CTR mode = mode || MODE; var keyIv = this.getBytesFromSecret(secret); var cipher = forge.aes.createEncryptionCipher(keyIv, mode); cipher.start(keyIv); cipher.update(forge.util.createBuffer(data)); cipher.finish(); if (encoder === 'url') { return base64url(cipher.output.data); } return forge.util.encode64(cipher.output.data); }, /** * Decrypt AES encrypted data * @param {String} data The data to decrypt * @param {String} secret The secret to use in decryption in Base64 format * @param {String} [encoder = 'base64'] base64 or url encoding * @param {String} [mode='CTR'] The mode to use in decryption. 'CBC', 'CFB', 'OFB', 'CTR' are allowed modes. * @return {String} The decrypted data */ decryptAes: function (data, secret, encoder, mode) { // mode = CBC, CFB, OFB, CTR mode = mode || MODE; var keyIv = this.getBytesFromSecret(secret); var cipher = forge.aes.createDecryptionCipher(keyIv, mode); cipher.start(keyIv); var decoded; if (encoder === 'url') { decoded = base64url.decode(data); } else { decoded = forge.util.decode64(data); } cipher.update(forge.util.createBuffer(decoded)); cipher.finish(); return cipher.output.data; }, /** * Create a signature (RSA-SHA1) for the message * @param {String} message The message to sign * @returns {String} The signature in Base64 */ sign: function (message) { var md = forge.md.sha1.create(); md.update(message, 'utf8'); return forge.util.encode64(this._key.sign(md)); }, /** * Verify a signature (RSA-SHA1) for the message * @param {String} message The message signed * @param {String} signature The signature of the message in Base64 format * @returns {Boolean} True is the signature is successful verified */ verifySignature: function (message, signature) { var md = forge.md.sha1.create(); md.update(message, 'utf8'); try { return this._cert.publicKey.verify(md.digest().bytes(), forge.util.decode64(signature)); } catch (e) { return false; } }, /** * Verify that a X.509 certificate is generated by the CA * @param {String} pem The certificate to verify in pem format * @returns {Boolean} True if the X.509 certificate is original */ verifyCertificate: function (pem) { var certificate = forge.pki.certificateFromPem(pem); var issuerCert = caStore.getIssuer(certificate); if (issuerCert) { try { return issuerCert.verify(certificate); } catch (e) { return false; } } return false; } }); };