fork-openpgpjs/README-ECC.md

4.0 KiB

Elliptic Curve Cryptography support for OpenPGPjs

Description

This work is to provide an implementation of RFC 6637 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.

> 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 <http://gnu.org/licenses/gpl.html>
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 for the elliptic curve cryptography. MIT license.

  • Aes required to implement RFC 3394 Key wrap and Key Unwrap functions. BSD License.

Examples

Generate new key

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

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.

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
  • OpenPGP Message Format RFC 4880
  • Advanced Encryption Standard (AES) Key Wrap Algorithm RFC 3394
  • A JavaScript component for the Advanced Encryption Standard (AES) AES
  • Fast elliptic-curve cryptography in a plain javascript implementation Elliptic