diff --git a/README-ECC.md b/README-ECC.md deleted file mode 100644 index 6454dc61..00000000 --- a/README-ECC.md +++ /dev/null @@ -1,134 +0,0 @@ -# Elliptic Curve Cryptography support for OpenPGPjs - -## Description - -This work is to provide an implementation of [RFC 6637](http://www.ietf.org/rfc/rfc6637.txt) -for OpenPGP.js. - -## Compatibility with GnuPG - -In order to assure compatibility of the provided implementation with RFC 6637, -the keys and messages were tested against GnuPG version v2.1.8, compiled -with a beta version of libgcrypt v1.7.0-beta262. - -It was tested that keys, messages, and signatures generated by GnuPG -were imported correctly. Also keys, messages and signatures generated by this -implementation are correctly imported by GnuPG. - -```txt -> gpg2 --homedir ../home --version -gpg (GnuPG) 2.1.8 -libgcrypt 1.7.0-beta262 -Copyright (C) 2015 Free Software Foundation, Inc. -License GPLv3+: GNU GPL version 3 or later -This is free software: you are free to change and redistribute it. -There is NO WARRANTY, to the extent permitted by law. - -Home: ../home -Supported algorithms: -Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA -Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH, - CAMELLIA128, CAMELLIA192, CAMELLIA256 -Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224 -Compression: Uncompressed, ZIP, ZLIB -``` - -## Extra dependencies - -There are two new dependencies: - -* [Elliptic](https://github.com/indutny/elliptic/) for the elliptic curve - cryptography. MIT license. - -* [Aes](https://github.com/cryptocoinjs/aes) required to implement RFC 3394 - Key wrap and Key Unwrap functions. BSD License. - -## Examples - -### Generate new key - -```js -var openpgp = require('openpgp'); - -var options = { - curve: 'secp256k1', - userIds: {name: 'Hamlet', email: 'hamlet@example.net'}, - passphrase: 'To be, or not to be: that is the question' -}; - -openpgp.generateKey(options).then(function(key) { - // success - var privkey = key.privateKeyArmored; - var pubkey = key.publicKeyArmored; -}).catch(function(error) { - // failure -}); -``` - -### Generate keypair from bitcoin key - -```js -var openpgp = require('openpgp'); -var bs58check = require('bs58check'); - -var wif = 'KyiAchQgMKuXQu89j6k6UVZQj7brK6cM79JfmDvkNXPVW24L1thi'; -var buff = bs58check.decode(wif); -var privateKey = buff.slice(1, -1); -privateKey = openpgp.util.bin2str(privateKey); - -var options = { - curve: 'secp256k1', - userIds: {name: 'Hamlet', email: 'hamlet@example.net'}, - passphrase: 'To be, or not to be: that is the question', - material: { - key: privateKey, - subkey: privateKey - } -}; - -openpgp.generateKey(options).then(function(key) { - // success - var privkey = key.privateKeyArmored; - var pubkey = key.publicKeyArmored; -}).catch(function(error) { - // failure -}); -``` - -### Signature, encryption and decryption - -The normal operations: signature, encryption and decryption require -no modifications. - -```js -var openpgp = require('openpgp'); - -var keyData = '-----BEGIN PGP PUBLIC KEY BLOCK ... END PGP PUBLIC KEY BLOCK-----'; -var key = openpgp.key.readArmored(keyData); - -openpgp.encrypt({publicKeys: key.keys, data: 'Hello, World!'}).then(function(msg) { - // success -}).catch(function(error) { - // failure -}); -``` - -## Possible improvements - -* The dependency with AES library can be eliminated, a suitable AES decrypt - function is provided. It is only used by the wrap and unwrap functions - in the crypto/rfc3394.js file. - -## Note - -Although the example uses the same value to generate the main key, and -the subkey, it is a recommended practice to use different keys. -The main key is used for signature and the subkeys are used for encryption. - -## Resources - -* Elliptic Curve Cryptography (ECC) in OpenPGP [RFC 6637](http://www.ietf.org/rfc/rfc6637.txt) -* OpenPGP Message Format [RFC 4880](http://www.ietf.org/rfc/rfc4880.txt) -* Advanced Encryption Standard (AES) Key Wrap Algorithm [RFC 3394](http://www.ietf.org/rfc/rfc3394.txt) -* A JavaScript component for the Advanced Encryption Standard (AES) [AES](https://github.com/cryptocoinjs/aes) -* Fast elliptic-curve cryptography in a plain javascript implementation [Elliptic](https://github.com/indutny/elliptic/) diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index 912633ab..0c16a44d 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -65,10 +65,9 @@ export default { * Encrypts data using the specified public key multiprecision integers * and the specified algorithm. * @param {module:enums.publicKey} algo Algorithm to be used (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}) - * @param {Array} publicParams Algorithm dependent multiprecision integers + * @param {Array} publicParams Algorithm dependent params * @param {module:type/mpi} data Data to be encrypted as MPI - * @return {Array} if RSA an module:type/mpi; - * if elgamal encryption an array of two module:type/mpi is returned; otherwise null + * @return {Array} encrypted session key parameters */ publicKeyEncrypt: function(algo, publicParams, data, fingerprint) { var types = this.getEncSessionKeyParamTypes(algo); @@ -111,17 +110,13 @@ export default { * Decrypts data using the specified public key multiprecision integers of the private key, * the specified secretMPIs of the private key and the specified algorithm. * @param {module:enums.publicKey} algo Algorithm to be used (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1}) - * @param {Array} publicParams Algorithm dependent multiprecision integers - * of the public key part of the private key - * @param {Array} secretMPIs Algorithm dependent multiprecision integers - * of the private key used - * @param {module:type/mpi} data Data to be encrypted as MPI + * @param {Array} keyIntegers Algorithm dependent params + * @param {String} fingerprint Recipient fingerprint * @return {module:type/mpi} returns a big integer containing the decrypted data; otherwise null */ publicKeyDecrypt: function(algo, keyIntegers, dataIntegers, fingerprint) { var p; - var bn = (function() { switch (algo) { case 'rsa_encrypt_sign': @@ -163,9 +158,9 @@ export default { return result; }, - /** Returns the number of integers comprising the private key of an algorithm + /** Returns the types comprising the private key of an algorithm * @param {String} algo The public key algorithm - * @return {Integer} The number of integers. + * @return {Array} The array of types */ getPrivKeyParamTypes: function(algo) { switch (algo) { @@ -196,10 +191,10 @@ export default { } }, - getPrivKeyParamCount: function(algo) { - return this.getPrivKeyParamTypes(algo).length; - }, - + /** Returns the types comprising the public key of an algorithm + * @param {String} algo The public key algorithm + * @return {Array} The array of types + */ getPubKeyParamTypes: function(algo) { // Algorithm-Specific Fields for RSA public keys: // - a multiprecision integer (MPI) of RSA public modulus n; @@ -230,7 +225,7 @@ export default { // Algorithm-Specific Fields for ECDH public keys: // - OID of curve; // - MPI of EC point representing public key. - // - variable-length field containing KDF parameters. + // - KDF: variable-length field containing KDF parameters. case 'ecdh': return ['oid', 'mpi', 'kdf']; default: @@ -238,10 +233,10 @@ export default { } }, - getPubKeyParamCount: function(algo) { - return this.getPubKeyParamTypes(algo).length; - }, - + /** Returns the types comprising the encrypted session key of an algorithm + * @param {String} algo The public key algorithm + * @return {Array} The array of types + */ getEncSessionKeyParamTypes: function(algo) { switch (algo) { // Algorithm-Specific Fields for RSA encrypted session keys: @@ -258,7 +253,7 @@ export default { // Algorithm-Specific Fields for ECDH encrypted session keys: // - MPI containing the ephemeral key used to establish the shared secret - // - ECDHSymmetricKey + // - ECDH Symmetric Key case 'ecdh': return ['mpi', 'ecdh_symkey']; @@ -267,10 +262,10 @@ export default { } }, - getEncSessionKeyParamCount: function(algo) { - return this.getEncSessionKeyParamTypes(algo).length; - }, - + /** Generate algorithm-specific key parameters + * @param {String} algo The public key algorithm + * @return {Array} The array of parameters + */ generateParams: function(algo, bits, curve) { var types = this.getPubKeyParamTypes(algo).concat(this.getPrivKeyParamTypes(algo)); switch (algo) { diff --git a/src/packet/public_key.js b/src/packet/public_key.js index faf8eec1..d8f5a33e 100644 --- a/src/packet/public_key.js +++ b/src/packet/public_key.js @@ -134,7 +134,7 @@ PublicKey.prototype.write = function () { } arr.push(new Uint8Array([enums.write(enums.publicKey, this.algorithm)])); - var paramCount = crypto.getPubKeyParamCount(this.algorithm); + var paramCount = crypto.getPubKeyParamTypes(this.algorithm).length; for (var i = 0; i < paramCount; i++) { arr.push(this.params[i].write()); @@ -189,7 +189,7 @@ PublicKey.prototype.getFingerprint = function () { toHash = this.writeOld(); this.fingerprint = util.Uint8Array2str(crypto.hash.sha1(toHash)); } else if (this.version === 3) { - var paramCount = crypto.getPubKeyParamCount(this.algorithm); + var paramCount = crypto.getPubKeyParamTypes(this.algorithm).length; for (var i = 0; i < paramCount; i++) { toHash += this.params[i].toBytes(); } diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index 94a5e703..a666175b 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -103,7 +103,7 @@ function parse_cleartext_params(hash_algorithm, cleartext, algorithm) { function write_cleartext_params(hash_algorithm, algorithm, params) { var arr = []; - var numPublicParams = crypto.getPubKeyParamCount(algorithm); + var numPublicParams = crypto.getPubKeyParamTypes(algorithm).length; for (var i = numPublicParams; i < params.length; i++) { arr.push(params[i].write()); @@ -288,6 +288,6 @@ SecretKey.prototype.clearPrivateParams = function () { if (!this.encrypted) { throw new Error('If secret key is not encrypted, clearing private MPIs is irreversible.'); } - this.params = this.params.slice(0, crypto.getPubKeyParamCount(this.algorithm)); + this.params = this.params.slice(0, crypto.getPubKeyParamTypes(this.algorithm).length); this.isDecrypted = false; };