Add explicit key type parameter in openpgp.generateKey (#1179)
- Changes `openpgp.generateKey` to accept an explicit `type` parameter, instead of inferring its value from the `curve` or `rsaBits` params - Introduces `config.minRsaBits` to set minimum key size of RSA key generation
This commit is contained in:
parent
92887a0948
commit
724775816f
6
openpgp.d.ts
vendored
6
openpgp.d.ts
vendored
|
@ -310,6 +310,7 @@ export namespace config {
|
||||||
let ignoreMdcError: boolean;
|
let ignoreMdcError: boolean;
|
||||||
let checksumRequired: boolean;
|
let checksumRequired: boolean;
|
||||||
let rsaBlinding: boolean;
|
let rsaBlinding: boolean;
|
||||||
|
let minRsaBits: number;
|
||||||
let passwordCollisionCheck: boolean;
|
let passwordCollisionCheck: boolean;
|
||||||
let revocationsExpire: boolean;
|
let revocationsExpire: boolean;
|
||||||
let useNative: boolean;
|
let useNative: boolean;
|
||||||
|
@ -621,9 +622,10 @@ export type EllipticCurveName = 'ed25519' | 'curve25519' | 'p256' | 'p384' | 'p5
|
||||||
interface KeyOptions {
|
interface KeyOptions {
|
||||||
userIds: UserId[]; // generating a key with no user defined results in error
|
userIds: UserId[]; // generating a key with no user defined results in error
|
||||||
passphrase?: string;
|
passphrase?: string;
|
||||||
numBits?: number;
|
type?: 'ecc' | 'rsa';
|
||||||
keyExpirationTime?: number;
|
|
||||||
curve?: EllipticCurveName;
|
curve?: EllipticCurveName;
|
||||||
|
rsaBits?: number;
|
||||||
|
keyExpirationTime?: number;
|
||||||
date?: Date;
|
date?: Date;
|
||||||
subkeys?: KeyOptions[];
|
subkeys?: KeyOptions[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,11 @@ export default {
|
||||||
* @property {Boolean} rsaBlinding
|
* @property {Boolean} rsaBlinding
|
||||||
*/
|
*/
|
||||||
rsaBlinding: true,
|
rsaBlinding: true,
|
||||||
|
/**
|
||||||
|
* @memberof module:config
|
||||||
|
* @property {Number} minRsaBits Minimum RSA key size allowed for key generation
|
||||||
|
*/
|
||||||
|
minRsaBits: 2048,
|
||||||
/**
|
/**
|
||||||
* Work-around for rare GPG decryption bug when encrypting with multiple passwords.
|
* Work-around for rare GPG decryption bug when encrypting with multiple passwords.
|
||||||
* **Slower and slightly less secure**
|
* **Slower and slightly less secure**
|
||||||
|
|
|
@ -37,21 +37,16 @@ import { unarmor } from '../encoding/armor';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new OpenPGP key. Supports RSA and ECC keys.
|
* Generates a new OpenPGP key. Supports RSA and ECC keys.
|
||||||
* Primary and subkey will be of same type.
|
* By default, primary and subkeys will be of same type.
|
||||||
* @param {module:enums.publicKey} [options.keyType=module:enums.publicKey.rsaEncryptSign]
|
* @param {ecc|rsa} options.type The primary key algorithm type: ECC or RSA
|
||||||
* To indicate what type of key to make.
|
* @param {String} options.curve Elliptic curve for ECC keys
|
||||||
* RSA is 1. See {@link https://tools.ietf.org/html/rfc4880#section-9.1}
|
* @param {Integer} options.rsaBits Number of bits for RSA keys
|
||||||
* @param {Integer} options.rsaBits number of bits for the key creation.
|
* @param {Array<String|Object>} options.userIds User IDs as strings or objects: 'Jo Doe <info@jo.com>' or { name:'Jo Doe', email:'info@jo.com' }
|
||||||
* @param {String|Array<String>} options.userIds
|
* @param {String} options.passphrase Passphrase used to encrypt the resulting private key
|
||||||
* Assumes already in form of "User Name <username@email.com>"
|
* @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires
|
||||||
* If array is used, the first userId is set as primary user Id
|
* @param {Date} options.date Creation date of the key and the key signatures
|
||||||
* @param {String} options.passphrase The passphrase used to encrypt the resulting private key
|
* @param {Array<Object>} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}]
|
||||||
* @param {Number} [options.keyExpirationTime=0]
|
* sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt
|
||||||
* The number of seconds after the key creation time that the key expires
|
|
||||||
* @param {String} options.curve (optional) elliptic curve for ECC keys
|
|
||||||
* @param {Date} options.date Override the creation date of the key and the key signatures
|
|
||||||
* @param {Array<Object>} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}]
|
|
||||||
* sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt
|
|
||||||
* @returns {Promise<module:key.Key>}
|
* @returns {Promise<module:key.Key>}
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
|
@ -68,16 +63,12 @@ export async function generate(options) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys.
|
* Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys.
|
||||||
* @param {module:key.Key} options.privateKey The private key to reformat
|
* @param {module:key.Key} options.privateKey The private key to reformat
|
||||||
* @param {module:enums.publicKey} [options.keyType=module:enums.publicKey.rsaEncryptSign]
|
* @param {Array<String|Object>} options.userIds User IDs as strings or objects: 'Jo Doe <info@jo.com>' or { name:'Jo Doe', email:'info@jo.com' }
|
||||||
* @param {String|Array<String>} options.userIds
|
* @param {String} options.passphrase Passphrase used to encrypt the resulting private key
|
||||||
* Assumes already in form of "User Name <username@email.com>"
|
* @param {Number} options.keyExpirationTime Number of seconds from the key creation time after which the key expires
|
||||||
* If array is used, the first userId is set as primary user Id
|
* @param {Date} options.date Override the creation date of the key and the key signatures
|
||||||
* @param {String} options.passphrase The passphrase used to encrypt the resulting private key
|
* @param {Array<Object>} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}]
|
||||||
* @param {Number} [options.keyExpirationTime=0]
|
|
||||||
* The number of seconds after the key creation time that the key expires
|
|
||||||
* @param {Date} options.date Override the creation date of the key and the key signatures
|
|
||||||
* @param {Array<Object>} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}]
|
|
||||||
*
|
*
|
||||||
* @returns {Promise<module:key.Key>}
|
* @returns {Promise<module:key.Key>}
|
||||||
* @async
|
* @async
|
||||||
|
|
|
@ -327,6 +327,7 @@ export async function isAeadSupported(keys, date = new Date(), userIds = []) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sanitizeKeyOptions(options, subkeyDefaults = {}) {
|
export function sanitizeKeyOptions(options, subkeyDefaults = {}) {
|
||||||
|
options.type = options.type || subkeyDefaults.type;
|
||||||
options.curve = options.curve || subkeyDefaults.curve;
|
options.curve = options.curve || subkeyDefaults.curve;
|
||||||
options.rsaBits = options.rsaBits || subkeyDefaults.rsaBits;
|
options.rsaBits = options.rsaBits || subkeyDefaults.rsaBits;
|
||||||
options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime;
|
options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime;
|
||||||
|
@ -335,24 +336,27 @@ export function sanitizeKeyOptions(options, subkeyDefaults = {}) {
|
||||||
|
|
||||||
options.sign = options.sign || false;
|
options.sign = options.sign || false;
|
||||||
|
|
||||||
if (options.curve) {
|
switch (options.type) {
|
||||||
try {
|
case 'ecc':
|
||||||
options.curve = enums.write(enums.curve, options.curve);
|
try {
|
||||||
} catch (e) {
|
options.curve = enums.write(enums.curve, options.curve);
|
||||||
throw new Error('Not valid curve.');
|
} catch (e) {
|
||||||
}
|
throw new Error('Invalid curve');
|
||||||
if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) {
|
}
|
||||||
options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519;
|
if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) {
|
||||||
}
|
options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519;
|
||||||
if (options.sign) {
|
}
|
||||||
options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa;
|
if (options.sign) {
|
||||||
} else {
|
options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa;
|
||||||
options.algorithm = enums.publicKey.ecdh;
|
} else {
|
||||||
}
|
options.algorithm = enums.publicKey.ecdh;
|
||||||
} else if (options.rsaBits) {
|
}
|
||||||
options.algorithm = enums.publicKey.rsaEncryptSign;
|
break;
|
||||||
} else {
|
case 'rsa':
|
||||||
throw new Error('Unrecognized key type');
|
options.algorithm = enums.publicKey.rsaEncryptSign;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported key type ${options.type}`);
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import {
|
||||||
PublicSubkeyPacket,
|
PublicSubkeyPacket,
|
||||||
SignaturePacket
|
SignaturePacket
|
||||||
} from '../packet';
|
} from '../packet';
|
||||||
|
import config from '../config';
|
||||||
import enums from '../enums';
|
import enums from '../enums';
|
||||||
import util from '../util';
|
import util from '../util';
|
||||||
import User from './user';
|
import User from './user';
|
||||||
|
@ -861,12 +862,12 @@ class Key {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new OpenPGP subkey, and returns a clone of the Key object with the new subkey added.
|
* Generates a new OpenPGP subkey, and returns a clone of the Key object with the new subkey added.
|
||||||
* Supports RSA and ECC keys. Defaults to the algorithm and bit size/curve of the primary key.
|
* Supports RSA and ECC keys. Defaults to the algorithm and bit size/curve of the primary key. DSA primary keys default to RSA subkeys.
|
||||||
* @param {Integer} options.rsaBits number of bits for the key creation.
|
* @param {ecc|rsa} options.type The subkey algorithm: ECC or RSA
|
||||||
* @param {Number} [options.keyExpirationTime=0]
|
* @param {String} options.curve (optional) Elliptic curve for ECC keys
|
||||||
* The number of seconds after the key creation time that the key expires
|
* @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys
|
||||||
* @param {String} options.curve (optional) Elliptic curve for ECC keys
|
* @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires
|
||||||
* @param {Date} options.date (optional) Override the creation date of the key and the key signatures
|
* @param {Date} options.date (optional) Override the creation date of the key and the key signatures
|
||||||
* @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false
|
* @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false
|
||||||
* @returns {Promise<module:key.Key>}
|
* @returns {Promise<module:key.Key>}
|
||||||
* @async
|
* @async
|
||||||
|
@ -878,14 +879,17 @@ class Key {
|
||||||
if (options.passphrase) {
|
if (options.passphrase) {
|
||||||
throw new Error("Subkey could not be encrypted here, please encrypt whole key");
|
throw new Error("Subkey could not be encrypted here, please encrypt whole key");
|
||||||
}
|
}
|
||||||
if (util.getWebCryptoAll() && options.rsaBits < 2048) {
|
if (options.rsaBits < config.minRsaBits) {
|
||||||
throw new Error('When using webCrypto rsaBits should be 2048 or 4096, found: ' + options.rsaBits);
|
throw new Error(`rsaBits should be at least ${config.minRsaBits}, got: ${options.rsaBits}`);
|
||||||
}
|
}
|
||||||
const secretKeyPacket = this.primaryKey;
|
const secretKeyPacket = this.primaryKey;
|
||||||
if (!secretKeyPacket.isDecrypted()) {
|
if (!secretKeyPacket.isDecrypted()) {
|
||||||
throw new Error("Key is not decrypted");
|
throw new Error("Key is not decrypted");
|
||||||
}
|
}
|
||||||
const defaultOptions = secretKeyPacket.getAlgorithmInfo();
|
const defaultOptions = secretKeyPacket.getAlgorithmInfo();
|
||||||
|
defaultOptions.type = defaultOptions.curve ? 'ecc' : 'rsa'; // DSA keys default to RSA
|
||||||
|
defaultOptions.rsaBits = defaultOptions.bits || 4096;
|
||||||
|
defaultOptions.curve = defaultOptions.curve || 'curve25519';
|
||||||
options = helper.sanitizeKeyOptions(options, defaultOptions);
|
options = helper.sanitizeKeyOptions(options, defaultOptions);
|
||||||
const keyPacket = await helper.generateSecretSubkey(options);
|
const keyPacket = await helper.generateSecretSubkey(options);
|
||||||
const bindingSignature = await helper.createBindingSignature(keyPacket, secretKeyPacket, options);
|
const bindingSignature = await helper.createBindingSignature(keyPacket, secretKeyPacket, options);
|
||||||
|
|
|
@ -62,28 +62,28 @@ if (globalThis.ReadableStream) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new OpenPGP key pair. Supports RSA and ECC keys. Primary and subkey will be of same type.
|
* Generates a new OpenPGP key pair. Supports RSA and ECC keys. By default, primary and subkeys will be of same type.
|
||||||
* @param {Array<Object>} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
|
* @param {ecc|rsa} type (optional) The primary key algorithm type: ECC (default) or RSA
|
||||||
* @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key
|
* @param {Array<String|Object>} userIds User IDs as strings or objects: 'Jo Doe <info@jo.com>' or { name:'Jo Doe', email:'info@jo.com' }
|
||||||
* @param {Number} rsaBits (optional) number of bits for RSA keys: 2048 or 4096.
|
* @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key
|
||||||
* @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires
|
* @param {Number} rsaBits (optional) Number of bits for RSA keys, defaults to 4096
|
||||||
* @param {String} curve (optional) elliptic curve for ECC keys:
|
* @param {String} curve (optional) Elliptic curve for ECC keys:
|
||||||
* curve25519, p256, p384, p521, secp256k1,
|
* curve25519 (default), p256, p384, p521, secp256k1,
|
||||||
* brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1.
|
* brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1
|
||||||
* @param {Date} date (optional) override the creation date of the key and the key signatures
|
* @param {Date} date (optional) Override the creation date of the key and the key signatures
|
||||||
* @param {Array<Object>} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}]
|
* @param {Number} keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires
|
||||||
* sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt
|
* @param {Array<Object>} subkeys (optional) Options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}]
|
||||||
|
* sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt
|
||||||
* @returns {Promise<Object>} The generated key object in the form:
|
* @returns {Promise<Object>} The generated key object in the form:
|
||||||
* { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String }
|
* { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String }
|
||||||
* @async
|
* @async
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
export function generateKey({ userIds = [], passphrase = "", rsaBits = null, keyExpirationTime = 0, curve = "curve25519", date = new Date(), subkeys = [{}] }) {
|
export function generateKey({ userIds = [], passphrase = "", type = "ecc", rsaBits = 4096, curve = "curve25519", keyExpirationTime = 0, date = new Date(), subkeys = [{}] }) {
|
||||||
userIds = toArray(userIds);
|
userIds = toArray(userIds);
|
||||||
curve = rsaBits ? "" : curve;
|
const options = { userIds, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys };
|
||||||
const options = { userIds, passphrase, rsaBits, keyExpirationTime, curve, date, subkeys };
|
if (type === "rsa" && rsaBits < config.minRsaBits) {
|
||||||
if (util.getWebCryptoAll() && rsaBits && rsaBits < 2048) {
|
throw new Error(`rsaBits should be at least ${config.minRsaBits}, got: ${rsaBits}`);
|
||||||
throw new Error('rsaBits should be 2048 or 4096, found: ' + rsaBits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return generate(options).then(async key => {
|
return generate(options).then(async key => {
|
||||||
|
@ -103,10 +103,10 @@ export function generateKey({ userIds = [], passphrase = "", rsaBits = null, key
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reformats signature packets for a key and rewraps key object.
|
* Reformats signature packets for a key and rewraps key object.
|
||||||
* @param {Key} privateKey private key to reformat
|
* @param {Key} privateKey Private key to reformat
|
||||||
* @param {Array<Object>} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
|
* @param {Array<String|Object>} userIds User IDs as strings or objects: 'Jo Doe <info@jo.com>' or { name:'Jo Doe', email:'info@jo.com' }
|
||||||
* @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key
|
* @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key
|
||||||
* @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires
|
* @param {Number} keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires
|
||||||
* @returns {Promise<Object>} The generated key object in the form:
|
* @returns {Promise<Object>} The generated key object in the form:
|
||||||
* { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String }
|
* { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String }
|
||||||
* @async
|
* @async
|
||||||
|
|
|
@ -231,14 +231,15 @@ class PublicKeyPacket {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns algorithm information
|
* Returns algorithm information
|
||||||
* @returns {Object} An object of the form {algorithm: String, rsaBits:int, curve:String}
|
* @returns {Object} An object of the form {algorithm: String, bits:int, curve:String}
|
||||||
*/
|
*/
|
||||||
getAlgorithmInfo() {
|
getAlgorithmInfo() {
|
||||||
const result = {};
|
const result = {};
|
||||||
result.algorithm = this.algorithm;
|
result.algorithm = this.algorithm;
|
||||||
if (this.publicParams.n) {
|
// RSA, DSA or ElGamal public modulo
|
||||||
result.rsaBits = this.publicParams.n.length * 8;
|
const modulo = this.publicParams.n || this.publicParams.p;
|
||||||
result.bits = result.rsaBits; // Deprecated.
|
if (modulo) {
|
||||||
|
result.bits = modulo.length * 8;
|
||||||
} else {
|
} else {
|
||||||
result.curve = this.publicParams.oid.getName();
|
result.curve = this.publicParams.oid.getName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -405,7 +405,6 @@ class SecretKeyPacket extends PublicKeyPacket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async generate(bits, curve) {
|
async generate(bits, curve) {
|
||||||
const algo = enums.write(enums.publicKey, this.algorithm);
|
const algo = enums.write(enums.publicKey, this.algorithm);
|
||||||
const { privateParams, publicParams } = await crypto.generateParams(algo, bits, curve);
|
const { privateParams, publicParams } = await crypto.generateParams(algo, bits, curve);
|
||||||
|
|
|
@ -14,7 +14,7 @@ const expect = chai.expect;
|
||||||
const native = util.getWebCrypto() || util.getNodeCrypto();
|
const native = util.getWebCrypto() || util.getNodeCrypto();
|
||||||
module.exports = () => (!native ? describe.skip : describe)('basic RSA cryptography with native crypto', function () {
|
module.exports = () => (!native ? describe.skip : describe)('basic RSA cryptography with native crypto', function () {
|
||||||
it('generate rsa key', async function() {
|
it('generate rsa key', async function() {
|
||||||
const bits = util.getWebCryptoAll() ? 2048 : 1024;
|
const bits = 1024;
|
||||||
const keyObject = await crypto.publicKey.rsa.generate(bits, 65537);
|
const keyObject = await crypto.publicKey.rsa.generate(bits, 65537);
|
||||||
expect(keyObject.n).to.exist;
|
expect(keyObject.n).to.exist;
|
||||||
expect(keyObject.e).to.exist;
|
expect(keyObject.e).to.exist;
|
||||||
|
@ -25,7 +25,7 @@ module.exports = () => (!native ? describe.skip : describe)('basic RSA cryptogra
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sign and verify using generated key params', async function() {
|
it('sign and verify using generated key params', async function() {
|
||||||
const bits = util.getWebCryptoAll() ? 2048 : 1024;
|
const bits = 1024;
|
||||||
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
||||||
const message = await random.getRandomBytes(64);
|
const message = await random.getRandomBytes(64);
|
||||||
const hash_algo = openpgp.enums.write(openpgp.enums.hash, 'sha256');
|
const hash_algo = openpgp.enums.write(openpgp.enums.hash, 'sha256');
|
||||||
|
@ -38,7 +38,7 @@ module.exports = () => (!native ? describe.skip : describe)('basic RSA cryptogra
|
||||||
});
|
});
|
||||||
|
|
||||||
it('encrypt and decrypt using generated key params', async function() {
|
it('encrypt and decrypt using generated key params', async function() {
|
||||||
const bits = util.getWebCryptoAll() ? 2048 : 1024;
|
const bits = 1024;
|
||||||
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
||||||
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
||||||
const message = await crypto.generateSessionKey('aes256');
|
const message = await crypto.generateSessionKey('aes256');
|
||||||
|
@ -72,7 +72,7 @@ module.exports = () => (!native ? describe.skip : describe)('basic RSA cryptogra
|
||||||
});
|
});
|
||||||
|
|
||||||
it('compare native crypto and bn math sign', async function() {
|
it('compare native crypto and bn math sign', async function() {
|
||||||
const bits = util.getWebCrypto() ? 2048 : 1024;
|
const bits = 1024;
|
||||||
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
||||||
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
||||||
const message = await random.getRandomBytes(64);
|
const message = await random.getRandomBytes(64);
|
||||||
|
@ -98,7 +98,7 @@ module.exports = () => (!native ? describe.skip : describe)('basic RSA cryptogra
|
||||||
});
|
});
|
||||||
|
|
||||||
it('compare native crypto and bn math verify', async function() {
|
it('compare native crypto and bn math verify', async function() {
|
||||||
const bits = util.getWebCrypto() ? 2048 : 1024;
|
const bits = 1024;
|
||||||
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
const { publicParams, privateParams } = await crypto.generateParams(openpgp.enums.publicKey.rsaSign, bits);
|
||||||
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
const { n, e, d, p, q, u } = { ...publicParams, ...privateParams };
|
||||||
const message = await random.getRandomBytes(64);
|
const message = await random.getRandomBytes(64);
|
||||||
|
|
|
@ -244,7 +244,7 @@ module.exports = () => {
|
||||||
describe('RSA parameter validation', function() {
|
describe('RSA parameter validation', function() {
|
||||||
let rsaKey;
|
let rsaKey;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
rsaKey = (await openpgp.generateKey({ rsaBits: 2048, userIds: [{ name: 'Test', email: 'test@test.com' }] })).key;
|
rsaKey = (await openpgp.generateKey({ type: 'rsa', rsaBits: 2048, userIds: [{ name: 'Test', email: 'test@test.com' }] })).key;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('generated RSA params are valid', async function() {
|
it('generated RSA params are valid', async function() {
|
||||||
|
|
|
@ -1917,6 +1917,34 @@ vqBGKJzmO5q3cECw
|
||||||
=X9kJ
|
=X9kJ
|
||||||
-----END PGP PRIVATE KEY BLOCK-----`;
|
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||||
|
|
||||||
|
const dsaPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
|
|
||||||
|
lQNTBF69PO8RCACHP4KLQcYOPGsGV9owTZvxnvHvvrY8W0v8xDUL3y6CLc05srF1
|
||||||
|
kQp/81iUfP5g57BEiDpJV95kMh+ulBthIOGnuMCkodJjuBICB4K6BtFTV4Fw1Q5S
|
||||||
|
S7aLC9beCaMvvGHXsK6MbknYl+IVJY7Zmml1qUSrBIQFGp5kqdhIX4o+OrzZ1zYj
|
||||||
|
ALicqzD7Zx2VRjGNQv7UKv4CkBOC8ncdnq/4/OQeOYFzVbCOf+sJhTgz6yxjHJVC
|
||||||
|
fLk7w8l2v1zV11VJuc8cQiQ9g8tjbKgLMsbyzy7gl4m9MSCdinG36XZuPibZrSm0
|
||||||
|
H8gKAdd1FT84a3/qU2rtLLR0y8tCxBj89Xx/AQCv7CDmwoU+/yGpBVVl1mh0ZUkA
|
||||||
|
/VJUhnJfv5MIOIi3AQf8CS9HrEmYJg/A3z0DcvcwIu/9gqpRLTqH1iT5o4BCg2j+
|
||||||
|
Cog2ExYkQl1OEPkEQ1lKJSnD8MDwO3BlkJ4cD0VSKxlnwd9dsu9m2+F8T+K1hoA7
|
||||||
|
PfH89TjD5HrEaGAYIdivLYSwoTNOO+fY8FoVC0RR9pFNOmjiTU5PZZedOxAql5Os
|
||||||
|
Hp2bYhky0G9trjo8Mt6CGhvgA3dAKyONftLQr9HSM0GKacFV+nRd9TGCPNZidKU8
|
||||||
|
MDa/SB/08y1bBGX5FK5wwiZ6H5qD8VAUobH3kwKlrg0nL00/EqtYHJqvJ2gkT5/v
|
||||||
|
h8+z4R4TuYiy4kKF2FLPd5OjdA31IVDoVgCwF0WHLgf/X9AiTr/DPs/5dIYN1+hf
|
||||||
|
UJwqjzr3dlokRwx3CVDcOVsdkWRwb8cvxubbsIorvUrF02IhYjHJMjIHT/zFt2zA
|
||||||
|
+VPzO4zabUlawWVepPEwrCtXgvn9aXqjhAYbilG3UZamhfstGUmbmvWVDadALwby
|
||||||
|
EO8u2pfLhI2lep63V/+KtUOLhfk8jKRSvxvxlYAvMi7sK8kB+lYy17XKN+IMYgf8
|
||||||
|
gMFV6XGKpdmMSV3jOvat8cI6vnRO0i+g3jANP3PfrFEivat/rVgxo67r4rxezfFn
|
||||||
|
J29qwB9rgbRgMBGsbDvIlQNV/NWFvHy2uQAEKn5eX4CoLsCZoR2VfK3BwBCxhYDp
|
||||||
|
/wAA/0GSmI9MlMnLadFNlcX2Bm4i15quZAGF8JxwHbj1dhdUEYq0E1Rlc3QgPHRl
|
||||||
|
c3RAdGVzdC5pbz6IlAQTEQgAPBYhBAq6lCI5EfrbHP1qZCxnOy/rlEGVBQJevTzv
|
||||||
|
AhsDBQsJCAcCAyICAQYVCgkICwIEFgIDAQIeBwIXgAAKCRAsZzsv65RBlUPoAP9Q
|
||||||
|
aTCWpHWZkvZzC8VU64O76fHp31rLWlcZFttuDNLyeAEAhOxkQHk6GR88R+EF5mrn
|
||||||
|
clr63t9Q4wreqOlO0NR5/9k=
|
||||||
|
=UW2O
|
||||||
|
-----END PGP PRIVATE KEY BLOCK-----
|
||||||
|
`;
|
||||||
|
|
||||||
const uidlessKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
const uidlessKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
|
|
||||||
xcMFBF8/lc8BCACwwWWyNdfZ9Qjz8zc4sFGNfHXITscT7WCMuXgC2BbFwiSD
|
xcMFBF8/lc8BCACwwWWyNdfZ9Qjz8zc4sFGNfHXITscT7WCMuXgC2BbFwiSD
|
||||||
|
@ -2244,6 +2272,20 @@ function versionSpecificTests() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Generate key - default values', function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = { userIds: [userId] };
|
||||||
|
return openpgp.generateKey(opt).then(function({ key }) {
|
||||||
|
expect(key.isDecrypted()).to.be.true;
|
||||||
|
expect(key.getAlgorithmInfo().algorithm).to.equal('eddsa');
|
||||||
|
expect(key.users.length).to.equal(1);
|
||||||
|
expect(key.users[0].userId.userid).to.equal(userId);
|
||||||
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
|
expect(key.subKeys).to.have.length(1);
|
||||||
|
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Generate key - two subkeys with default values', function() {
|
it('Generate key - two subkeys with default values', function() {
|
||||||
const userId = 'test <a@b.com>';
|
const userId = 'test <a@b.com>';
|
||||||
const opt = { userIds: [userId], passphrase: '123', subkeys:[{},{}] };
|
const opt = { userIds: [userId], passphrase: '123', subkeys:[{},{}] };
|
||||||
|
@ -2258,20 +2300,24 @@ function versionSpecificTests() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Generate RSA key - two subkeys with default values', function() {
|
it('Generate RSA key - two subkeys with default values', async function() {
|
||||||
const userId = 'test <a@b.com>';
|
const rsaBits = 512;
|
||||||
const opt = { rsaBits: 512, userIds: [userId], passphrase: '123', subkeys:[{},{}] };
|
const minRsaBits = openpgp.config.minRsaBits;
|
||||||
if (util.getWebCryptoAll()) { opt.rsaBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
openpgp.config.minRsaBits = rsaBits;
|
||||||
|
|
||||||
return openpgp.generateKey(opt).then(function(key) {
|
const userId = 'test <a@b.com>';
|
||||||
key = key.key;
|
const opt = { type: 'rsa', rsaBits, userIds: [userId], passphrase: '123', subkeys:[{},{}] };
|
||||||
|
try {
|
||||||
|
const { key } = await openpgp.generateKey(opt);
|
||||||
expect(key.users.length).to.equal(1);
|
expect(key.users.length).to.equal(1);
|
||||||
expect(key.users[0].userId.userid).to.equal(userId);
|
expect(key.users[0].userId.userid).to.equal(userId);
|
||||||
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
expect(key.subKeys).to.have.length(2);
|
expect(key.subKeys).to.have.length(2);
|
||||||
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('rsaEncryptSign');
|
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('rsaEncryptSign');
|
||||||
expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('rsaEncryptSign');
|
expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('rsaEncryptSign');
|
||||||
});
|
} finally {
|
||||||
|
openpgp.config.minRsaBits = minRsaBits;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Generate key - one signing subkey', function() {
|
it('Generate key - one signing subkey', function() {
|
||||||
|
@ -2309,20 +2355,24 @@ function versionSpecificTests() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Generate key - override main RSA key options for subkey', function() {
|
it('Generate key - override main RSA key options for subkey', async function() {
|
||||||
|
const rsaBits = 512;
|
||||||
|
const minRsaBits = openpgp.config.minRsaBits;
|
||||||
|
openpgp.config.minRsaBits = rsaBits;
|
||||||
|
|
||||||
const userId = 'test <a@b.com>';
|
const userId = 'test <a@b.com>';
|
||||||
const opt = { rsaBits: 512, userIds: [userId], passphrase: '123', subkeys:[{ curve: 'curve25519' }] };
|
const opt = { type: 'rsa', rsaBits, userIds: [userId], passphrase: '123', subkeys:[{ type: 'ecc', curve: 'curve25519' }] };
|
||||||
if (util.getWebCryptoAll()) { opt.rsaBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys
|
try {
|
||||||
return openpgp.generateKey(opt).then(function(key) {
|
const { key } = await openpgp.generateKey(opt);
|
||||||
key = key.key;
|
|
||||||
expect(key.users.length).to.equal(1);
|
expect(key.users.length).to.equal(1);
|
||||||
expect(key.users[0].userId.userid).to.equal(userId);
|
expect(key.users[0].userId.userid).to.equal(userId);
|
||||||
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
expect(key.getAlgorithmInfo().algorithm).to.equal('rsaEncryptSign');
|
expect(key.getAlgorithmInfo().algorithm).to.equal('rsaEncryptSign');
|
||||||
expect(key.getAlgorithmInfo().bits).to.equal(opt.rsaBits);
|
expect(key.getAlgorithmInfo().bits).to.equal(opt.rsaBits);
|
||||||
expect(key.getAlgorithmInfo().rsaBits).to.equal(key.getAlgorithmInfo().bits);
|
|
||||||
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
||||||
});
|
} finally {
|
||||||
|
openpgp.config.minRsaBits = minRsaBits;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Encrypt key with new passphrase', async function() {
|
it('Encrypt key with new passphrase', async function() {
|
||||||
|
@ -3407,12 +3457,17 @@ VYGdb3eNlV8CfoEC
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('addSubkey functionality testing', function() {
|
describe('addSubkey functionality testing', function() {
|
||||||
let rsaBits;
|
const rsaBits = 1024;
|
||||||
let rsaOpt = {};
|
const rsaOpt = { type: 'rsa' };
|
||||||
if (util.getWebCryptoAll()) {
|
let minRsaBits;
|
||||||
rsaBits = 2048;
|
beforeEach(function() {
|
||||||
rsaOpt = { rsaBits: rsaBits };
|
minRsaBits = openpgp.config.minRsaBits;
|
||||||
}
|
openpgp.config.minRsaBits = rsaBits;
|
||||||
|
});
|
||||||
|
afterEach(function() {
|
||||||
|
openpgp.config.minRsaBits = minRsaBits;
|
||||||
|
});
|
||||||
|
|
||||||
it('create and add a new rsa subkey to stored rsa key', async function() {
|
it('create and add a new rsa subkey to stored rsa key', async function() {
|
||||||
const privateKey = await openpgp.readArmoredKey(priv_key_rsa);
|
const privateKey = await openpgp.readArmoredKey(priv_key_rsa);
|
||||||
await privateKey.decrypt('hello world');
|
await privateKey.decrypt('hello world');
|
||||||
|
@ -3425,12 +3480,40 @@ VYGdb3eNlV8CfoEC
|
||||||
expect(newPrivateKey.subKeys.length).to.be.equal(total + 1);
|
expect(newPrivateKey.subKeys.length).to.be.equal(total + 1);
|
||||||
const subkeyN = subKey.keyPacket.publicParams.n;
|
const subkeyN = subKey.keyPacket.publicParams.n;
|
||||||
const pkN = privateKey.primaryKey.publicParams.n;
|
const pkN = privateKey.primaryKey.publicParams.n;
|
||||||
expect(subkeyN.length).to.be.equal(rsaBits ? (rsaBits / 8) : pkN.length);
|
expect(subkeyN.length).to.be.equal(pkN.length);
|
||||||
expect(subKey.getAlgorithmInfo().algorithm).to.be.equal('rsaEncryptSign');
|
expect(subKey.getAlgorithmInfo().algorithm).to.be.equal('rsaEncryptSign');
|
||||||
expect(subKey.getAlgorithmInfo().rsaBits).to.be.equal(rsaBits || privateKey.getAlgorithmInfo().rsaBits);
|
expect(subKey.getAlgorithmInfo().bits).to.be.equal(privateKey.getAlgorithmInfo().bits);
|
||||||
await subKey.verify(newPrivateKey.primaryKey);
|
await subKey.verify(newPrivateKey.primaryKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Add a new default subkey to an rsaSign key', async function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = { type: 'rsa', rsaBits, userIds: [userId], subkeys: [] };
|
||||||
|
const { key } = await openpgp.generateKey(opt);
|
||||||
|
expect(key.subKeys).to.have.length(0);
|
||||||
|
key.keyPacket.algorithm = "rsaSign";
|
||||||
|
const newKey = await key.addSubkey();
|
||||||
|
expect(newKey.subKeys[0].getAlgorithmInfo().algorithm).to.equal('rsaEncryptSign');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Add a new default subkey to an ecc key', async function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = { type: 'ecc', userIds: [userId], subkeys: [] };
|
||||||
|
const { key } = await openpgp.generateKey(opt);
|
||||||
|
expect(key.subKeys).to.have.length(0);
|
||||||
|
const newKey = await key.addSubkey();
|
||||||
|
expect(newKey.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh');
|
||||||
|
expect(newKey.subKeys[0].getAlgorithmInfo().curve).to.equal('curve25519');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Add a new default subkey to a dsa key', async function() {
|
||||||
|
const key = await openpgp.readArmoredKey(dsaPrivateKey);
|
||||||
|
const total = key.subKeys.length;
|
||||||
|
const newKey = await key.addSubkey();
|
||||||
|
expect(newKey.subKeys[total].getAlgorithmInfo().algorithm).to.equal('rsaEncryptSign');
|
||||||
|
expect(newKey.subKeys[total].getAlgorithmInfo().bits).to.equal(Math.max(key.getAlgorithmInfo().bits, openpgp.config.minRsaBits));
|
||||||
|
});
|
||||||
|
|
||||||
it('should throw when trying to encrypt a subkey separately from key', async function() {
|
it('should throw when trying to encrypt a subkey separately from key', async function() {
|
||||||
const privateKey = await openpgp.readArmoredKey(priv_key_rsa);
|
const privateKey = await openpgp.readArmoredKey(priv_key_rsa);
|
||||||
await privateKey.decrypt('hello world');
|
await privateKey.decrypt('hello world');
|
||||||
|
@ -3454,7 +3537,7 @@ VYGdb3eNlV8CfoEC
|
||||||
await subKey.verify(importedPrivateKey.primaryKey);
|
await subKey.verify(importedPrivateKey.primaryKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('create and add a new ec subkey to a ec key', async function() {
|
it('create and add a new eddsa subkey to a eddsa key', async function() {
|
||||||
const userId = 'test <a@b.com>';
|
const userId = 'test <a@b.com>';
|
||||||
const opt = { curve: 'curve25519', userIds: [userId], subkeys:[] };
|
const opt = { curve: 'curve25519', userIds: [userId], subkeys:[] };
|
||||||
const privateKey = (await openpgp.generateKey(opt)).key;
|
const privateKey = (await openpgp.generateKey(opt)).key;
|
||||||
|
@ -3478,19 +3561,66 @@ VYGdb3eNlV8CfoEC
|
||||||
await subKey.verify(privateKey.primaryKey);
|
await subKey.verify(privateKey.primaryKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('create and add a new ec subkey to a rsa key', async function() {
|
it('create and add a new ecdsa subkey to a eddsa key', async function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = { curve: 'ed25519', userIds: [userId], subkeys:[] };
|
||||||
|
const privateKey = (await openpgp.generateKey(opt)).key;
|
||||||
|
const total = privateKey.subKeys.length;
|
||||||
|
let newPrivateKey = await privateKey.addSubkey({ curve: 'p256', sign: true });
|
||||||
|
newPrivateKey = await openpgp.readArmoredKey(newPrivateKey.armor());
|
||||||
|
const subKey = newPrivateKey.subKeys[total];
|
||||||
|
expect(subKey).to.exist;
|
||||||
|
expect(newPrivateKey.subKeys.length).to.be.equal(total + 1);
|
||||||
|
expect(newPrivateKey.getAlgorithmInfo().curve).to.be.equal('ed25519');
|
||||||
|
expect(subKey.getAlgorithmInfo().curve).to.be.equal('p256');
|
||||||
|
expect(newPrivateKey.getAlgorithmInfo().algorithm).to.be.equal('eddsa');
|
||||||
|
expect(subKey.getAlgorithmInfo().algorithm).to.be.equal('ecdsa');
|
||||||
|
|
||||||
|
await subKey.verify(privateKey.primaryKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('create and add a new ecc subkey to a rsa key', async function() {
|
||||||
const privateKey = await openpgp.readArmoredKey(priv_key_rsa);
|
const privateKey = await openpgp.readArmoredKey(priv_key_rsa);
|
||||||
await privateKey.decrypt('hello world');
|
await privateKey.decrypt('hello world');
|
||||||
const total = privateKey.subKeys.length;
|
const total = privateKey.subKeys.length;
|
||||||
const opt2 = { curve: 'curve25519' };
|
const opt2 = { type: 'ecc', curve: 'curve25519' };
|
||||||
let newPrivateKey = await privateKey.addSubkey(opt2);
|
let newPrivateKey = await privateKey.addSubkey(opt2);
|
||||||
const armoredKey = newPrivateKey.armor();
|
const armoredKey = newPrivateKey.armor();
|
||||||
newPrivateKey = await openpgp.readArmoredKey(armoredKey);
|
newPrivateKey = await openpgp.readArmoredKey(armoredKey);
|
||||||
|
expect(newPrivateKey.subKeys.length).to.be.equal(total + 1);
|
||||||
|
const subKey = newPrivateKey.subKeys[total];
|
||||||
|
expect(subKey).to.exist;
|
||||||
|
expect(subKey.getAlgorithmInfo().algorithm).to.be.equal('ecdh');
|
||||||
|
expect(subKey.getAlgorithmInfo().curve).to.be.equal(openpgp.enums.curve.curve25519);
|
||||||
|
await subKey.verify(privateKey.primaryKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('create and add a new rsa subkey to a ecc key', async function() {
|
||||||
|
const userId = 'test <a@b.com>';
|
||||||
|
const opt = { curve: 'ed25519', userIds: [userId], subkeys:[] };
|
||||||
|
const privateKey = (await openpgp.generateKey(opt)).key;
|
||||||
|
const total = privateKey.subKeys.length;
|
||||||
|
let newPrivateKey = await privateKey.addSubkey({ type: 'rsa' });
|
||||||
|
const armoredKey = newPrivateKey.armor();
|
||||||
|
newPrivateKey = await openpgp.readArmoredKey(armoredKey);
|
||||||
const subKey = newPrivateKey.subKeys[total];
|
const subKey = newPrivateKey.subKeys[total];
|
||||||
expect(subKey).to.exist;
|
expect(subKey).to.exist;
|
||||||
expect(newPrivateKey.subKeys.length).to.be.equal(total + 1);
|
expect(newPrivateKey.subKeys.length).to.be.equal(total + 1);
|
||||||
expect(subKey.keyPacket.publicParams.oid.getName()).to.be.equal(openpgp.enums.curve.curve25519);
|
expect(subKey.getAlgorithmInfo().bits).to.be.equal(4096);
|
||||||
expect(subKey.getAlgorithmInfo().algorithm).to.be.equal('ecdh');
|
expect(subKey.getAlgorithmInfo().algorithm).to.be.equal('rsaEncryptSign');
|
||||||
|
await subKey.verify(privateKey.primaryKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('create and add a new rsa subkey to a dsa key', async function() {
|
||||||
|
const privateKey = await openpgp.readArmoredKey(dsaPrivateKey);
|
||||||
|
const total = privateKey.subKeys.length;
|
||||||
|
let newPrivateKey = await privateKey.addSubkey({ type: 'rsa', rsaBits: 2048 });
|
||||||
|
newPrivateKey = await openpgp.readArmoredKey(newPrivateKey.armor());
|
||||||
|
expect(newPrivateKey.subKeys.length).to.be.equal(total + 1);
|
||||||
|
const subKey = newPrivateKey.subKeys[total];
|
||||||
|
expect(subKey).to.exist;
|
||||||
|
expect(subKey.getAlgorithmInfo().algorithm).to.be.equal('rsaEncryptSign');
|
||||||
|
expect(subKey.getAlgorithmInfo().bits).to.be.equal(2048);
|
||||||
await subKey.verify(privateKey.primaryKey);
|
await subKey.verify(privateKey.primaryKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../..');
|
const openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('../..');
|
||||||
const util = require('../../src/util');
|
|
||||||
|
|
||||||
const { readArmoredKey, Key, readArmoredCleartextMessage, CleartextMessage, enums, PacketList, SignaturePacket } = openpgp;
|
const { readArmoredKey, Key, readArmoredCleartextMessage, CleartextMessage, enums, PacketList, SignaturePacket } = openpgp;
|
||||||
const key = require('../../src/key');
|
const key = require('../../src/key');
|
||||||
|
@ -12,7 +11,8 @@ const expect = chai.expect;
|
||||||
async function generateTestData() {
|
async function generateTestData() {
|
||||||
const victimPrivKey = await key.generate({
|
const victimPrivKey = await key.generate({
|
||||||
userIds: ['Victim <victim@example.com>'],
|
userIds: ['Victim <victim@example.com>'],
|
||||||
rsaBits: util.getWebCryptoAll() ? 2048 : 1024,
|
type: 'rsa',
|
||||||
|
rsaBits: 1024,
|
||||||
subkeys: [{
|
subkeys: [{
|
||||||
sign: true
|
sign: true
|
||||||
}]
|
}]
|
||||||
|
@ -21,7 +21,8 @@ async function generateTestData() {
|
||||||
|
|
||||||
const attackerPrivKey = await key.generate({
|
const attackerPrivKey = await key.generate({
|
||||||
userIds: ['Attacker <attacker@example.com>'],
|
userIds: ['Attacker <attacker@example.com>'],
|
||||||
rsaBits: util.getWebCryptoAll() ? 2048 : 1024,
|
type: 'rsa',
|
||||||
|
rsaBits: 1024,
|
||||||
subkeys: [],
|
subkeys: [],
|
||||||
sign: false
|
sign: false
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user