mirror of
https://github.com/openpgpjs/openpgpjs.git
synced 2025-06-06 14:16:42 +00:00
Support generating Curve448 and Curve25519 keys (new format)
Neither type is set as default for now, since they are not widely supported.
This commit is contained in:
parent
1509364a49
commit
24c644207d
6
openpgp.d.ts
vendored
6
openpgp.d.ts
vendored
@ -816,7 +816,7 @@ export namespace enums {
|
|||||||
aeadEncryptedData = 20,
|
aeadEncryptedData = 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type publicKeyNames = 'rsaEncryptSign' | 'rsaEncrypt' | 'rsaSign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsa' | 'aedh' | 'aedsa';
|
export type publicKeyNames = 'rsaEncryptSign' | 'rsaEncrypt' | 'rsaSign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsa' | 'ed25519Legacy' | 'aedh' | 'aedsa' | 'ed25519' | 'x25519' | 'ed448' | 'x448';
|
||||||
enum publicKey {
|
enum publicKey {
|
||||||
rsaEncryptSign = 1,
|
rsaEncryptSign = 1,
|
||||||
rsaEncrypt = 2,
|
rsaEncrypt = 2,
|
||||||
@ -830,6 +830,10 @@ export namespace enums {
|
|||||||
eddsaLegacy = 22,
|
eddsaLegacy = 22,
|
||||||
aedh = 23,
|
aedh = 23,
|
||||||
aedsa = 24,
|
aedsa = 24,
|
||||||
|
x25519 = 25,
|
||||||
|
x448 = 26,
|
||||||
|
ed25519 = 27,
|
||||||
|
ed448 = 28
|
||||||
}
|
}
|
||||||
|
|
||||||
enum curve {
|
enum curve {
|
||||||
|
@ -36,14 +36,14 @@ ed25519.hash = bytes => sha512(bytes);
|
|||||||
* @returns {Promise<{ A: Uint8Array, seed: Uint8Array }>}
|
* @returns {Promise<{ A: Uint8Array, seed: Uint8Array }>}
|
||||||
*/
|
*/
|
||||||
export async function generate(algo) {
|
export async function generate(algo) {
|
||||||
const seed = getRandomBytes(getPayloadSize(algo));
|
|
||||||
|
|
||||||
switch (algo) {
|
switch (algo) {
|
||||||
case enums.publicKey.ed25519: {
|
case enums.publicKey.ed25519: {
|
||||||
|
const seed = getRandomBytes(getPayloadSize(algo));
|
||||||
const { publicKey: A } = ed25519.sign.keyPair.fromSeed(seed);
|
const { publicKey: A } = ed25519.sign.keyPair.fromSeed(seed);
|
||||||
return { A, seed };
|
return { A, seed };
|
||||||
}
|
}
|
||||||
case enums.publicKey.ed448: {
|
case enums.publicKey.ed448: {
|
||||||
|
const seed = ed448.utils.randomPrivateKey();
|
||||||
const A = ed448.getPublicKey(seed);
|
const A = ed448.getPublicKey(seed);
|
||||||
return { A, seed };
|
return { A, seed };
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,9 @@ function createKey(packetlist) {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new OpenPGP key. Supports RSA and ECC keys.
|
* Generates a new OpenPGP key. Supports RSA and ECC keys, as well as the newer Curve448 and Curve25519 keys.
|
||||||
* By default, primary and subkeys will be of same type.
|
* By default, primary and subkeys will be of same type.
|
||||||
* @param {ecc|rsa} options.type The primary key algorithm type: ECC or RSA
|
* @param {ecc|rsa|curve448|curve25519} options.type The primary key algorithm type: ECC, RSA, Curve448 or Curve25519 (new format).
|
||||||
* @param {String} options.curve Elliptic curve for ECC keys
|
* @param {String} options.curve Elliptic curve for ECC keys
|
||||||
* @param {Integer} options.rsaBits Number of bits for RSA keys
|
* @param {Integer} options.rsaBits Number of bits for RSA keys
|
||||||
* @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 {Array<String|Object>} options.userIDs User IDs as strings or objects: 'Jo Doe <info@jo.com>' or { name:'Jo Doe', email:'info@jo.com' }
|
||||||
|
@ -326,7 +326,7 @@ export function sanitizeKeyOptions(options, subkeyDefaults = {}) {
|
|||||||
options.sign = options.sign || false;
|
options.sign = options.sign || false;
|
||||||
|
|
||||||
switch (options.type) {
|
switch (options.type) {
|
||||||
case 'ecc':
|
case 'ecc': // NB: this case also handles legacy eddsa and x25519 keys, based on `options.curve`
|
||||||
try {
|
try {
|
||||||
options.curve = enums.write(enums.curve, options.curve);
|
options.curve = enums.write(enums.curve, options.curve);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -341,6 +341,12 @@ export function sanitizeKeyOptions(options, subkeyDefaults = {}) {
|
|||||||
options.algorithm = enums.publicKey.ecdh;
|
options.algorithm = enums.publicKey.ecdh;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'curve25519':
|
||||||
|
options.algorithm = options.sign ? enums.publicKey.ed25519 : enums.publicKey.x25519;
|
||||||
|
break;
|
||||||
|
case 'curve448':
|
||||||
|
options.algorithm = options.sign ? enums.publicKey.ed448 : enums.publicKey.x448;
|
||||||
|
break;
|
||||||
case 'rsa':
|
case 'rsa':
|
||||||
options.algorithm = enums.publicKey.rsaEncryptSign;
|
options.algorithm = enums.publicKey.rsaEncryptSign;
|
||||||
break;
|
break;
|
||||||
|
@ -198,8 +198,10 @@ class PrivateKey extends PublicKey {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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. DSA primary keys default to RSA subkeys.
|
* Supports RSA and ECC keys, as well as the newer Curve448 and Curve25519.
|
||||||
* @param {ecc|rsa} options.type The subkey algorithm: ECC or RSA
|
* Defaults to the algorithm and bit size/curve of the primary key. DSA primary keys default to RSA subkeys.
|
||||||
|
* @param {ecc|rsa|curve25519|curve448} options.type The subkey algorithm: ECC, RSA, Curve448 or Curve25519 (new format).
|
||||||
|
* Note: Curve448 and Curve25519 are not widely supported yet.
|
||||||
* @param {String} options.curve (optional) Elliptic curve for ECC keys
|
* @param {String} options.curve (optional) Elliptic curve for ECC keys
|
||||||
* @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys
|
* @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys
|
||||||
* @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires
|
* @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires
|
||||||
@ -225,7 +227,7 @@ class PrivateKey extends PublicKey {
|
|||||||
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.type = getDefaultSubkeyType(defaultOptions.algorithm);
|
||||||
defaultOptions.rsaBits = defaultOptions.bits || 4096;
|
defaultOptions.rsaBits = defaultOptions.bits || 4096;
|
||||||
defaultOptions.curve = defaultOptions.curve || 'curve25519';
|
defaultOptions.curve = defaultOptions.curve || 'curve25519';
|
||||||
options = helper.sanitizeKeyOptions(options, defaultOptions);
|
options = helper.sanitizeKeyOptions(options, defaultOptions);
|
||||||
@ -238,4 +240,25 @@ class PrivateKey extends PublicKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDefaultSubkeyType(algoName) {
|
||||||
|
const algo = enums.write(enums.publicKey, algoName);
|
||||||
|
// NB: no encryption-only algos, since they cannot be in primary keys
|
||||||
|
switch (algo) {
|
||||||
|
case enums.publicKey.rsaEncrypt:
|
||||||
|
case enums.publicKey.rsaEncryptSign:
|
||||||
|
case enums.publicKey.rsaSign:
|
||||||
|
case enums.publicKey.dsa:
|
||||||
|
return 'rsa';
|
||||||
|
case enums.publicKey.ecdsa:
|
||||||
|
case enums.publicKey.eddsaLegacy:
|
||||||
|
return 'ecc';
|
||||||
|
case enums.publicKey.ed25519:
|
||||||
|
return 'curve25519';
|
||||||
|
case enums.publicKey.ed448:
|
||||||
|
return 'curve448';
|
||||||
|
default:
|
||||||
|
throw new Error('Unsupported algorithm');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default PrivateKey;
|
export default PrivateKey;
|
||||||
|
@ -32,11 +32,13 @@ import { checkKeyRequirements } from './key/helper';
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new OpenPGP key pair. Supports RSA and ECC keys. By default, primary and subkeys will be of same type.
|
* Generates a new OpenPGP key pair. Supports RSA and ECC keys, as well as the newer Curve448 and Curve25519 keys.
|
||||||
|
* By default, primary and subkeys will be of same type.
|
||||||
* The generated primary key will have signing capabilities. By default, one subkey with encryption capabilities is also generated.
|
* The generated primary key will have signing capabilities. By default, one subkey with encryption capabilities is also generated.
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @param {Object|Array<Object>} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }`
|
* @param {Object|Array<Object>} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }`
|
||||||
* @param {'ecc'|'rsa'} [options.type='ecc'] - The primary key algorithm type: ECC (default) or RSA
|
* @param {'ecc'|'rsa'|'curve448'|'curve25519'} [options.type='ecc'] - The primary key algorithm type: ECC (default), RSA, Curve448 or Curve25519 (new format).
|
||||||
|
* Note: Curve448 and Curve25519 (new format) are not widely supported yet.
|
||||||
* @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the generated private key. If omitted or empty, the key won't be encrypted.
|
* @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the generated private key. If omitted or empty, the key won't be encrypted.
|
||||||
* @param {Number} [options.rsaBits=4096] - Number of bits for RSA keys
|
* @param {Number} [options.rsaBits=4096] - Number of bits for RSA keys
|
||||||
* @param {String} [options.curve='curve25519'] - Elliptic curve for ECC keys:
|
* @param {String} [options.curve='curve25519'] - Elliptic curve for ECC keys:
|
||||||
|
@ -193,13 +193,13 @@ export default () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const curves = ['curve25519', 'p256', 'p384', 'p521', 'secp256k1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1'];
|
const curves = ['curve25519Legacy', 'p256', 'p384', 'p521', 'secp256k1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1'];
|
||||||
curves.forEach(curve => {
|
curves.forEach(curve => {
|
||||||
describe(`ECC ${curve} parameter validation`, () => {
|
describe(`ECC ${curve} parameter validation`, () => {
|
||||||
let ecdsaKey;
|
let ecdsaKey;
|
||||||
let ecdhKey;
|
let ecdhKey;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
if (curve !== 'curve25519') {
|
if (curve !== 'curve25519Legacy') {
|
||||||
ecdsaKey = await generatePrivateKeyObject({ curve });
|
ecdsaKey = await generatePrivateKeyObject({ curve });
|
||||||
ecdhKey = ecdsaKey.subkeys[0];
|
ecdhKey = ecdsaKey.subkeys[0];
|
||||||
} else {
|
} else {
|
||||||
@ -247,58 +247,45 @@ export default () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Ed448/X448 parameter validation', function() {
|
// new EdDSA/XECDH algos
|
||||||
let eddsaKey;
|
['25519', '448'].forEach(curveID => {
|
||||||
let ecdhXKey;
|
describe(`Ed${curveID}/X${curveID} parameter validation`, function() {
|
||||||
before(async () => {
|
let eddsaKey;
|
||||||
eddsaKey = await openpgp.readKey({ armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
let ecdhXKey;
|
||||||
|
before(async () => {
|
||||||
|
eddsaKey = await generatePrivateKeyObject({ type: `curve${curveID}` });
|
||||||
|
ecdhXKey = eddsaKey.subkeys[0];
|
||||||
|
});
|
||||||
|
|
||||||
xXsEZCWHXBwwtqciq6ZFU13s+dyhkWR5tOEmF1oX8OiP1B5ypfqyGVM8DkQh
|
it(`Ed${curveID} params should be valid`, async function() {
|
||||||
5eTIMwB1oqJCROANoyA0q2dSigAAbDA5xr74DeClPPXC4ZXJ9uzuJWKvQvE8
|
await expect(eddsaKey.keyPacket.validate()).to.not.be.rejected;
|
||||||
x3EflhgoQCGBM7JfvH5zwdrJvPt8RKDvm0QkZzhPvnFoHnzNBHRlc3TCugQQ
|
});
|
||||||
HAgAPgWCZCWHXAQLCQcICZDsN6h/ys3ppwMVCAoEFgACAQIZAQKbAwIeARYh
|
|
||||||
BOJyE9P2eIcU2N2Ne+w3qH/KzemnAAAh1hTFCcEU77bU3YelrJTCNIOQnvt7
|
|
||||||
Hs6yZz2053CQTOC+wHkUQLaYYBEXSNyLZxoyv+NuGTiwbuYtAOlbE2erM7Cx
|
|
||||||
8B2Qz7M29UkFLMBUfb+yi+gTYYUWCXVQ7Um7MGjjgUG8+9p452i6f28mhRD8
|
|
||||||
tTgNAMd5BGQlh1wavTIFgILtbzrqQCiwDGx0YcFNzu9+FZ8vK5Mmm7UEZj0a
|
|
||||||
y7FWQtZw8tTaU6mY+RrSa52RjzkGLtQAQO++tgYqc+BnCFdCZ3ZYPRvD3mof
|
|
||||||
ffoo3l4xmto+iyvJZbQ4wQPXttg7VjCpEfOsL9TW9Xs09aIbysKmBBgcCAAq
|
|
||||||
BYJkJYdcCZDsN6h/ys3ppwKbDBYhBOJyE9P2eIcU2N2Ne+w3qH/KzemnAAC0
|
|
||||||
6/eZhh/Oj2gRdab2JeFGWACGIRDKxPXsWRCXR4YrSxcvCKK6rOvsyxQsgIsJ
|
|
||||||
JyPYkRPfmbKcseUDAEkSBLAfeizDGh7ea0GOdIMhwE/CW4f/H8ULbwi36y13
|
|
||||||
x3oMNVaYsI9dZ588Gpi8XYy2jOtqIPQ1AA==
|
|
||||||
-----END PGP PRIVATE KEY BLOCK-----` });
|
|
||||||
ecdhXKey = eddsaKey.subkeys[0];
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Ed448 params should be valid', async function() {
|
it(`detect invalid Ed${curveID} public point`, async function() {
|
||||||
await expect(eddsaKey.keyPacket.validate()).to.not.be.rejected;
|
const eddsaKeyPacket = await cloneKeyPacket(eddsaKey);
|
||||||
});
|
const A = eddsaKeyPacket.publicParams.A;
|
||||||
|
A[0]++;
|
||||||
|
await expect(eddsaKeyPacket.validate()).to.be.rejectedWith('Key is invalid');
|
||||||
|
|
||||||
it('detect invalid Ed448 public point', async function() {
|
const infA = new Uint8Array(A.length);
|
||||||
const eddsaKeyPacket = await cloneKeyPacket(eddsaKey);
|
eddsaKeyPacket.publicParams.A = infA;
|
||||||
const A = eddsaKeyPacket.publicParams.A;
|
await expect(eddsaKeyPacket.validate()).to.be.rejectedWith('Key is invalid');
|
||||||
A[0]++;
|
});
|
||||||
await expect(eddsaKeyPacket.validate()).to.be.rejectedWith('Key is invalid');
|
|
||||||
|
|
||||||
const infA = new Uint8Array(A.length);
|
it(`X${curveID} params should be valid`, async function() {
|
||||||
eddsaKeyPacket.publicParams.A = infA;
|
await expect(ecdhXKey.keyPacket.validate()).to.not.be.rejected;
|
||||||
await expect(eddsaKeyPacket.validate()).to.be.rejectedWith('Key is invalid');
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('X448 params should be valid', async function() {
|
it(`detect invalid X${curveID} public point`, async function() {
|
||||||
await expect(ecdhXKey.keyPacket.validate()).to.not.be.rejected;
|
const ecdhXKeyPacket = await cloneKeyPacket(ecdhXKey);
|
||||||
});
|
const A = ecdhXKeyPacket.publicParams.A;
|
||||||
|
A[0]++;
|
||||||
|
await expect(ecdhXKeyPacket.validate()).to.be.rejectedWith('Key is invalid');
|
||||||
|
|
||||||
it('detect invalid x448 public point', async function() {
|
const infA = new Uint8Array(A.length);
|
||||||
const ecdhXKeyPacket = await cloneKeyPacket(ecdhXKey);
|
ecdhXKeyPacket.publicParams.A = infA;
|
||||||
const A = ecdhXKeyPacket.publicParams.A;
|
await expect(ecdhXKeyPacket.validate()).to.be.rejectedWith('Key is invalid');
|
||||||
A[0]++;
|
});
|
||||||
await expect(ecdhXKeyPacket.validate()).to.be.rejectedWith('Key is invalid');
|
|
||||||
|
|
||||||
const infA = new Uint8Array(A.length);
|
|
||||||
ecdhXKeyPacket.publicParams.A = infA;
|
|
||||||
await expect(ecdhXKeyPacket.validate()).to.be.rejectedWith('Key is invalid');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2509,6 +2509,54 @@ function versionSpecificTests() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Generate Ed25519 key (new format) - default subkey', async function() {
|
||||||
|
const userID = { name: 'test', email: 'a@b.com' };
|
||||||
|
const opt = { type: 'curve25519', userIDs: [userID], passphrase: '123', format: 'object' };
|
||||||
|
const { privateKey: key } = await openpgp.generateKey(opt);
|
||||||
|
expect(key.users.length).to.equal(1);
|
||||||
|
expect(key.users[0].userID.userID).to.equal('test <a@b.com>');
|
||||||
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
|
expect(key.getAlgorithmInfo().algorithm).to.equal('ed25519');
|
||||||
|
expect(key.subkeys).to.have.length(1);
|
||||||
|
expect(key.subkeys[0].getAlgorithmInfo().algorithm).to.equal('x25519');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate Ed25519 key (new format) - one signing subkey', async function() {
|
||||||
|
const userID = { name: 'test', email: 'a@b.com' };
|
||||||
|
const opt = { type: 'curve25519', userIDs: [userID], passphrase: '123', format: 'object', subkeys:[{ sign: true }] };
|
||||||
|
const { privateKey: key } = await openpgp.generateKey(opt);
|
||||||
|
expect(key.users.length).to.equal(1);
|
||||||
|
expect(key.users[0].userID.userID).to.equal('test <a@b.com>');
|
||||||
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
|
expect(key.getAlgorithmInfo().algorithm).to.equal('ed25519');
|
||||||
|
expect(key.subkeys).to.have.length(1);
|
||||||
|
expect(key.subkeys[0].getAlgorithmInfo().algorithm).to.equal('ed25519');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate Ed448 key - default subkey', async function() {
|
||||||
|
const userID = { name: 'test', email: 'a@b.com' };
|
||||||
|
const opt = { type: 'curve448', userIDs: [userID], passphrase: '123', format: 'object' };
|
||||||
|
const { privateKey: key } = await openpgp.generateKey(opt);
|
||||||
|
expect(key.users.length).to.equal(1);
|
||||||
|
expect(key.users[0].userID.userID).to.equal('test <a@b.com>');
|
||||||
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
|
expect(key.getAlgorithmInfo().algorithm).to.equal('ed448');
|
||||||
|
expect(key.subkeys).to.have.length(1);
|
||||||
|
expect(key.subkeys[0].getAlgorithmInfo().algorithm).to.equal('x448');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Generate Ed448 key - one signing subkey', async function() {
|
||||||
|
const userID = { name: 'test', email: 'a@b.com' };
|
||||||
|
const opt = { type: 'curve448', userIDs: [userID], passphrase: '123', format: 'object', subkeys:[{ sign: true }] };
|
||||||
|
const { privateKey: key } = await openpgp.generateKey(opt);
|
||||||
|
expect(key.users.length).to.equal(1);
|
||||||
|
expect(key.users[0].userID.userID).to.equal('test <a@b.com>');
|
||||||
|
expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true;
|
||||||
|
expect(key.getAlgorithmInfo().algorithm).to.equal('ed448');
|
||||||
|
expect(key.subkeys).to.have.length(1);
|
||||||
|
expect(key.subkeys[0].getAlgorithmInfo().algorithm).to.equal('ed448');
|
||||||
|
});
|
||||||
|
|
||||||
it('Generate key - one signing subkey', function() {
|
it('Generate key - one signing subkey', function() {
|
||||||
const userID = { name: 'test', email: 'a@b.com' };
|
const userID = { name: 'test', email: 'a@b.com' };
|
||||||
const opt = { userIDs: [userID], passphrase: '123', format: 'object', subkeys:[{}, { sign: true }] };
|
const opt = { userIDs: [userID], passphrase: '123', format: 'object', subkeys:[{}, { sign: true }] };
|
||||||
@ -4196,6 +4244,16 @@ VYGdb3eNlV8CfoEC
|
|||||||
expect(newKey.subkeys[0].getAlgorithmInfo().curve).to.equal('curve25519');
|
expect(newKey.subkeys[0].getAlgorithmInfo().curve).to.equal('curve25519');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Add a new default subkey to an Ed488 key', async function() {
|
||||||
|
const userID = { name: 'test', email: 'a@b.com' };
|
||||||
|
const opt = { type: 'curve448', userIDs: [userID], format: 'object', subkeys: [] };
|
||||||
|
const { privateKey: 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('x448');
|
||||||
|
expect(newKey.subkeys[0].getAlgorithmInfo().curve).to.be.undefined;
|
||||||
|
});
|
||||||
|
|
||||||
it('Add a new default subkey to a dsa key', async function() {
|
it('Add a new default subkey to a dsa key', async function() {
|
||||||
const key = await openpgp.readKey({ armoredKey: dsaPrivateKey });
|
const key = await openpgp.readKey({ armoredKey: dsaPrivateKey });
|
||||||
const total = key.subkeys.length;
|
const total = key.subkeys.length;
|
||||||
|
@ -4758,17 +4758,8 @@ sEj+v9LKoMTYZGMfp3qDVFLtkBE88eVmVjgJOoLhrsv7yh0PAA==
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('sign/verify with new Ed25519 format', async function () {
|
it('sign/verify with new Ed25519 format', async function () {
|
||||||
// v4 key, which we do not support generating
|
const userIDs = { name: 'Alice', email: 'info@alice.com' };
|
||||||
const privateKey = await openpgp.readKey({ armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
const { privateKey } = await openpgp.generateKey({ type: 'curve25519', userIDs, format: 'object' });
|
||||||
|
|
||||||
xUkEZBw5PBscroGar9fsilA0q9AX979pBhTNkGQ69vQGGW7kxRxNuABB+eAw
|
|
||||||
JrQ9A3o1gUJg28ORTQd72+kFo87184qR97a6rRGFzQR0ZXN0wogEEBsIAD4F
|
|
||||||
gmQcOTwECwkHCAmQT/m+Rl22Ps8DFQgKBBYAAgECGQECmwMCHgEWIQSUlOfm
|
|
||||||
G7MWJd2909ZP+b5GXbY+zwAAVs/4pWH4l7pWcTATBavVqSATMKi4A+usp89G
|
|
||||||
J/qaHc+qmcEpIMmPNvLQ7n4F4kEXk8Zwz+OXovVWLQ+Njl5gzooF
|
|
||||||
=wYg1
|
|
||||||
-----END PGP PRIVATE KEY BLOCK-----
|
|
||||||
` });
|
|
||||||
const plaintext = 'plaintext';
|
const plaintext = 'plaintext';
|
||||||
|
|
||||||
const signed = await openpgp.sign({
|
const signed = await openpgp.sign({
|
||||||
@ -4786,22 +4777,8 @@ J/qaHc+qmcEpIMmPNvLQ7n4F4kEXk8Zwz+OXovVWLQ+Njl5gzooF
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('sign/verify with Ed448', async function () {
|
it('sign/verify with Ed448', async function () {
|
||||||
const privateKey = await openpgp.readKey({ armoredKey: `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
const userIDs = { name: 'Alice', email: 'info@alice.com' };
|
||||||
|
const { privateKey } = await openpgp.generateKey({ type: 'curve448', userIDs, format: 'object' });
|
||||||
xX0GZRqLYhwAAAA5U/IaIOge/FoLzCetXKx029bdJHCz2hMFBRMuzq4msjaT
|
|
||||||
+hLeV6puyC/PeSEfaanqTuo31vvsti2AAIttr4GDGXF4vfPzbzkWV9dT4VVs
|
|
||||||
IU7QqLv1hzwZ+k7pHroRyXnUiYxRYHuzlg7Vw4CrAtN/8T65OMLAHgYfHAoA
|
|
||||||
AAA9BQJlGotiIqEGAxidsHRHDsyFTw1Q7OoGEAEnRnxthKMwVBqhIL2o+HUC
|
|
||||||
GwMCHgkCCwcDFQoIAhYAAycHAgAAAAA2KiC+Y+fhQ/48CkT9WrXTX9SCn3vH
|
|
||||||
z43Wb++AkmpWL1HQmrJE3S4gGltezZK2E9ovagzxKxVrL14uC6hs6kJ0JIiW
|
|
||||||
QSeMeexCTy+Gdr6j0wb4FhFNnoIu3yu2ABmZpFX/5/191YeWUryKFDAoUZmK
|
|
||||||
gQTSOzJEvyO0ACR5L4vV3ADceOAdG8/sqhE89rTSevFXng4JAM0XVXNlckEg
|
|
||||||
PFVzZXJBQHRlc3QudGVzdD7CwA0GExwKAAAALAUCZRqLYiKhBgMYnbB0Rw7M
|
|
||||||
hU8NUOzqBhABJ0Z8bYSjMFQaoSC9qPh1AhkBAAAAAFw/IH72M1iyzMWhbgtw
|
|
||||||
v0SR/XxvOIW/ZrT4Ix9236lvoOE4taL/D46CbZOjm7VAeOSfSdxt1xSKnoAL
|
|
||||||
RsCNQ8tVPjPXclzqr6R8MbPIgBWxKcMS2eStYpBbG5qAmc+K5jdA2xcl9iW5
|
|
||||||
bWleZ1LTah4lF6qCiD73IffADXtzw8iAMTX+0wM5N1tJUEGvgqe00ohRKiQA
|
|
||||||
-----END PGP PRIVATE KEY BLOCK-----` });
|
|
||||||
const plaintext = 'plaintext';
|
const plaintext = 'plaintext';
|
||||||
|
|
||||||
const signed = await openpgp.sign({
|
const signed = await openpgp.sign({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user