npm Build Status npm License Become a Patron
OpenCrypto is a lightweight, high performance, standard-compliant JavaScript library built on top of Web Cryptography API. This library makes it easier to implement cryptography in a browser with less code. It can convert and encode ASN.1, PEM and CryptoKey. OpenCrypto is created and maintained by SafeBash.
<script type="text/javascript" src="OpenCrypto.min.js"></script> // Initialize new OpenCrypto instance const crypt = new OpenCrypto()
or
import OpenCrypto from 'opencrypto' // Initialize new OpenCrypto instance const crypt = new OpenCrypto()
/** * Method that converts asymmetric private key from CryptoKey to PEM format * @param {CryptoKey} privateKey default: "undefined" */ crypt.cryptoPrivateToPem(privateKey).then(privatePem => { console.log(privatePem) }) /** * Method that converts asymmetric private key from PEM to CryptoKey format * @param {String} pem default: "undefined" * @param {Object} options default: depends on algorithm below * -- ECDH: { name: 'ECDH', usages: ['deriveKey', 'deriveBits'], isExtractable: true } * -- ECDSA: { name: 'ECDSA', usages: ['sign'], isExtractable: true } * -- RSA-OAEP: { name: 'RSA-OAEP', hash: { name: 'SHA-512' }, usages: ['decrypt', 'unwrapKey'], isExtractable: true } * -- RSA-PSS: { name: 'RSA-PSS', hash: { name: 'SHA-512' }, usages: ['sign'], isExtractable: true } */ crypt.pemPrivateToCrypto(pem, options).then(cryptoPrivate => { console.log(cryptoPrivate) }) /** * Method that converts asymmetric public key from CryptoKey to PEM format * @param {CryptoKey} publicKey default: "undefined" */ crypt.cryptoPublicToPem(publicKey).then(publicPem => { console.log(publicPem) }) /** * Method that converts asymmetric public key from PEM to CryptoKey format * @param {String} publicKey default: "undefined" * @param {Object} options default: depends on algorithm below * -- ECDH: { name: 'ECDH', usages: [], isExtractable: true } * -- ECDSA: { name: 'ECDSA', usages: ['verify'], isExtractable: true } * -- RSA-OAEP: { name: 'RSA-OAEP', hash: { name: 'SHA-512' }, usages: ['encrypt', 'wrapKey'], isExtractable: true } * -- RSA-PSS: { name: 'RSA-PSS', hash: { name: 'SHA-512' }, usages: ['verify'], isExtractable: true } */ crypt.pemPublicToCrypto(pem, options).then(cryptoPublic => { console.log(cryptoPublic) }) /** * Method that converts CryptoKey to base64 * @param {CryptoKey} key default: "undefined" * @param {String} type default: "secret: 'raw'; private: 'pkcs8'; public: 'spki'" */ crypt.cryptoToBase64(key, type).then(base64Key => { console.log(base64Key) }) /** * Method that converts base64 encoded key to CryptoKey * @param {String} key default: "undefined" * @param {Object} options default: depends on algorithm below * -- AES-GCM: { name: 'AES-GCM', length: 256, usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true } * -- AES-CBC: { name: 'AES-CBC', length: 256, usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true } * -- ECDH: { name: 'ECDH', namedCurve: 'P-256', usages: ['deriveKey', 'deriveBits'], isExtractable: true } * -- ECDSA: { name: 'ECDSA', namedCurve: 'P-256', usages: ['sign', 'verify'], isExtractable: true } * -- RSA-OAEP: { name: 'RSA-OAEP', hash: { name: 'SHA-512' }, usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true } * -- RSA-PSS: { name: 'RSA-PSS', hash: { name: 'SHA-512' }, usages: ['sign', 'verify'], isExtractable: true } */ crypt.base64ToCrypto(key, options).then(cryptoKey => { console.log(cryptoKey) })
/** * Method that generates asymmetric RSA-OAEP key pair * @param {Integer} modulusLength default: "2048" * @param {String} hash default: "SHA-512" * @param {String} paddingScheme default: "RSA-OAEP" * @param {Array} usages default: "['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']" * @param {Boolean} isExtractable default: "true" */ crypt.getRSAKeyPair(modulusLength, hash, paddingScheme, usages, isExtractable).then(keyPair => { console.log(keyPair.publicKey) console.log(keyPair.privateKey) }) /** * Method that encrypts data using asymmetric encryption * @param {CryptoKey} publicKey default: "undefined" * @param {ArrayBuffer} data default: "undefined" */ crypt.rsaEncrypt(publicKey, data).then(encryptedData => { console.log(encryptedData) }) /** * Method that decrypts data using asymmetric encryption * @param {CryptoKey} privateKey default: "undefined" * @param {String} encryptedData default: "undefined" */ crypt.rsaDecrypt(privateKey, encryptedData).then(decryptedData => { console.log(decryptedData) }) /** * Method that generates asymmetric Elliptic Curve Diffie-Hellman key pair * @param {String} curve default: "P-256" * @param {String} type default: "ECDH" * @param {Array} usages default: "['deriveKey', 'deriveBits']" * @param {Boolean} isExtractable default: "true" */ crypt.getECKeyPair(curve, type, usages, isExtractable).then(keyPair => { console.log(keyPair.privateKey) console.log(keyPair.publicKey) }) /** * Method that retrieves public key from private key * @param {CryptoKey} privateKey default: "undefined" * @param {Object} options default: depends on algorithm below * -- ECDH: { usages: ['deriveKey', 'deriveBits'], isExtractable: true } * -- ECDSA: { usages: ['sign', 'verify'], isExtractable: true } * -- RSA-OAEP: { usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true } * -- RSA-PSS: { usages: ['sign', 'verify'], isExtractable: true } */ crypt.getPublicKey(privateKey, options).then(publicKey => { console.log(publicKey) }) /** * Method that encrypts asymmetric private key using passphrase to enable storage in unsecure environment * @param {CryptoKey} privateKey default: "undefined" * @param {String} passphrase default: "undefined" * @param {Number} iterations default: "64000" * @param {String} hash default: "SHA-512" * @param {String} cipher default: "AES-GCM" * @param {Number} length default: "256" */ crypt.encryptPrivateKey(privateKey, passphrase, iterations, hash, cipher, length).then(encryptedPrivateKey => { console.log(encryptedPrivateKey) }) /** * Method that decrypts asymmetric private key using passphrase * @param {String} encryptedPrivateKey default: "undefined" * @param {String} passphrase default: "undefined" * @param {Object} options default: depends on algorithm below * -- ECDH: { name: 'ECDH', namedCurve: 'P-256', usages: ['deriveKey', 'deriveBits'], isExtractable: true } * -- ECDSA: { name: 'ECDSA', namedCurve: 'P-256', usages: ['sign'], isExtractable: true } * -- RSA-OAEP: { name: 'RSA-OAEP', hash: 'SHA-512', usages: ['decrypt', 'unwrapKey'], isExtractable: true } * -- RSA-PSS: { name: 'RSA-PSS', hash: 'SHA-512', usages: ['sign'], isExtractable: true } */ crypt.decryptPrivateKey(encryptedPrivateKey, passphrase, options).then(decryptedPrivateKey => { console.log(decryptedPrivateKey) }) /** * Method that performs ECDH key agreement * @param {CryptoKey} privateKey default: "undefined" * @param {CryptoKey} publicKey default: "undefined" * @param {Object} options default: "{ bitLength: 256, hkdfHash: 'SHA-512', hkdfSalt: "new UInt8Array()", hkdfInfo: "new UInt8Array()", cipher: 'AES-GCM', length: 256, usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true }" */ crypt.keyAgreement(privateKey, publicKey, options).then(sharedKey => { console.log(sharedKey) })
/** * Method that generates symmetric/shared key for AES encryption * @param {Integer} length default: "256" * @param {Object} options default: "{ cipher: 'AES-GCM', usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true }" */ crypt.getSharedKey(length, options).then(sharedKey => { console.log(sharedKey) }) /** * Method that encrypts keys * @param {CryptoKey} wrappingKey default: "undefined" * @param {CryptoKey} key default: "undefined" */ crypt.encryptKey(wrappingKey, key).then(encryptedKey => { console.log(encryptedKey) }) /** * Method that decrypts keys * @param {CryptoKey} unwrappingKey default: "undefined" * @param {String} encryptedKey default: "undefined" * @param {Object} options default: depends on algorithm below * -- AES-GCM: { type: 'raw', name: 'AES-GCM', length: 256, usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true } * -- AES-CBC: { type: 'raw', name: 'AES-CBC', length: 256, usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true } * -- ECDH: { type: "'pkcs8' or 'spki'", name: 'ECDH', namedCurve: 'P-256', usages: ['deriveKey', 'deriveBits'], isExtractable: true } * -- ECDSA: { type: "'pkcs8' or 'spki'", name: 'ECDSA', namedCurve: 'P-256', usages: ['sign', 'verify'], isExtractable: true } * -- RSA-OAEP: { type: "'pkcs8' or 'spki'", name: 'RSA-OAEP', hash: 'SHA-512', usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true } * -- RSA-PSS: { type: "'pkcs8' or 'spki'", name: 'RSA-PSS', hash: 'SHA-512', usages: ['sign', 'verify'], isExtractable: true } */ crypt.decryptKey(unwrappingKey, encryptedKey, options).then(decryptedKey => { console.log(decryptedKey) }) /** * Method that generates key signature using ECDSA or RSA-PSS * @param {CryptoKey} privateKey default: "undefined" * @param {CryptoKey} key default: "undefined" * @param {Object} options default: depends on algorithm below * -- ECDSA: { hash: 'SHA-512' } * -- RSA-PSS: { saltLength: 128 } */ crypt.signKey(privateKey, key, options).then(keySignature => { console.log(keySignature) }) /** * Method that verifies key signature using ECDSA or RSA-PSS * @param {CryptoKey} publicKey default: "undefined" * @param {CryptoKey} key default: "undefined" * @param {String} signature default: "undefined" * @param {Object} options default: depends on algorithm below * -- ECDSA: { hash: 'SHA-512' } * -- RSA-PSS: { saltLength: 128 } */ crypt.verifyKey(publicKey, key, signature, options).then(isValid => { console.log(isValid) }) /** * Method that generates signature of data using ECDSA or RSA-PSS * @param {CryptoKey} privateKey default: "undefined" * @param {ArrayBuffer} data default: "undefined" * @param {Object} options default: depends on algorithm below * -- ECDSA: { hash: 'SHA-512' } * -- RSA-PSS: { saltLength: 128 } */ crypt.sign(privateKey, data, options).then(signature => { console.log(signature) }) /** * Method that verifies data signature using ECDSA or RSA-PSS * @param {CryptoKey} publicKey default: "undefined" * @param {ArrayBuffer} data default: "undefined" * @param {String} signature default: "undefined" * @param {Object} options default: depends on algorithm below * -- ECDSA: { hash: 'SHA-512' } * -- RSA-PSS: { saltLength: 128 } */ crypt.verify(publicKey, data, signature, options).then(isValid => { console.log(isValid) }) /** * Method that encrypts data using symmetric/shared key * @param {CryptoKey} sharedKey default: "undefined" * @param {ArrayBuffer} data default: "undefined" */ crypt.encrypt(sharedKey, data).then(encryptedData => { console.log(encryptedData) }) /** * Method that decrypts data using symmetric/shared key * @param {CryptoKey} sharedKey default: "undefined" * @param {String} encryptedData default: "undefined" * @param {Object} options default: depends on algorithm below * -- AES-GCM: { cipher: 'AES-GCM' } * -- AES-CBC: { cipher: 'AES-CBC' } */ crypt.decrypt(sharedKey, encryptedData, options).then(decryptedData => { console.log(decryptedData) })
/** * Method that derives shared key from passphrase * @param {String} passphrase default: "undefined" * @param {ArrayBuffer} salt default: "undefined" * @param {Number} iterations default: "64000" * @param {Object} options default: "{ hash: 'SHA-512', length: 256, cipher: 'AES-GCM', usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true }" */ crypt.derivePassphraseKey(passphrase, salt, iterations, options).then(derivedKey => { console.log(derivedKey) }) /** * Method that derives hash from passphrase * @param {String} passphrase default: "undefined" * @param {ArrayBuffer} salt default: "undefined" salt * @param {Number} iterations default: "64000" * @param {Object} options default: "{ hash: 'SHA-512', length: 256, cipher: 'AES-GCM', usages: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], isExtractable: true }" */ crypt.hashPassphrase(passphrase, salt, iterations, options).then(hashedPassphrase => { console.log(derivedHash) }) /** * Method that generates fingerprint of EC, RSA and AES keys * @param {CryptoKey} key default: "undefined" * @param {Object} options default: { hash: 'SHA-512', isBuffer: false } */ crypt.getFingerprint(key, options).then(fingerprint => { console.log(fingerprint) })
/** * Method that generates random bytes using cryptographically secure PRNG * @param {Number} size default: "16" */ crypt.getRandomBytes(size).then(data => { console.log(data) })
RFC 5280
RFC 6090
RFC 5208
RFC 5480
RFC 5915
RFC 8018
RFC 3394
NIST SP 800-38A
NIST SP 800-38B
NIST SP 800-38D
NIST SP 800-56A
NIST SP 800-56C
NIST FIPS 180-4
Peter Bielak
Andrew Kozlik, Ph.D.
MIT