New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@digitalbazaar/x25519-key-agreement-key-2020

Package Overview
Dependencies
Maintainers
6
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@digitalbazaar/x25519-key-agreement-key-2020 - npm Package Compare versions

Comparing version 1.2.1 to 2.0.0

10

CHANGELOG.md
# x25519-key-agreement-key-2020 Changelog
## 2.0.0 - 2021-06-19
### Changed
- **BREAKING**: Upgrade to @digitalbazaar/ed25519-verification-key-2020@3
which changes the key format to multicodec.
## 1.2.1 - 2021-05-06
### Fixed
- Fix `package.json` browser section alias for `crypto.js` (was causing downstream
webpack errors).
- Fix `package.json` browser section alias for `crypto.js` (was causing
downstream webpack errors).

@@ -9,0 +15,0 @@ ## 1.2.0 - 2021-04-02

214

lib/X25519KeyAgreementKey2020.js

@@ -11,2 +11,12 @@ /*!

const SUITE_ID = 'X25519KeyAgreementKey2020';
// multibase base58-btc header
const MULTIBASE_BASE58BTC_HEADER = 'z';
// multicodec ed25519-pub header as varint
const MULTICODEC_ED25519_PUB_HEADER = new Uint8Array([0xed, 0x01]);
// multicodec ed25519-priv header as varint
const MULTICODEC_ED25519_PRIV_HEADER = new Uint8Array([0x80, 0x26]);
// multicodec ed25519-pub header as varint
const MULTICODEC_X25519_PUB_HEADER = new Uint8Array([0xec, 0x01]);
// multicodec ed25519-priv header as varint
const MULTICODEC_X25519_PRIV_HEADER = new Uint8Array([0x82, 0x26]);

@@ -30,7 +40,24 @@ export class X25519KeyAgreementKey2020 extends LDKeyPair {

this.type = SUITE_ID;
this.publicKeyMultibase = options.publicKeyMultibase;
if(!this.publicKeyMultibase) {
throw TypeError('The "publicKeyMultibase" parameter is required.');
const {publicKeyMultibase, privateKeyMultibase} = options;
if(!publicKeyMultibase) {
throw new TypeError('The "publicKeyMultibase" property is required.');
}
this.privateKeyMultibase = options.privateKeyMultibase;
if(!publicKeyMultibase || !_isValidKeyHeader(
publicKeyMultibase, MULTICODEC_X25519_PUB_HEADER)) {
throw new Error(
'"publicKeyMultibase" has invalid header bytes: ' +
`"${publicKeyMultibase}".`);
}
if(privateKeyMultibase && !_isValidKeyHeader(
privateKeyMultibase, MULTICODEC_X25519_PRIV_HEADER)) {
throw new Error('"privateKeyMultibase" has invalid header bytes.');
}
// assign valid key values
this.publicKeyMultibase = publicKeyMultibase;
this.privateKeyMultibase = privateKeyMultibase;
if(this.controller && !this.id) {

@@ -52,4 +79,6 @@ this.id = `${this.controller}#${this.fingerprint()}`;

return new X25519KeyAgreementKey2020({
publicKeyMultibase: _multibaseEncode({bytes: publicKey}),
privateKeyMultibase: _multibaseEncode({bytes: privateKey}),
publicKeyMultibase:
_multibaseEncode(MULTICODEC_X25519_PUB_HEADER, publicKey),
privateKeyMultibase:
_multibaseEncode(MULTICODEC_X25519_PRIV_HEADER, privateKey),
...options

@@ -95,7 +124,9 @@ });

// prefix with `z` to indicate multi-base base58btc encoding
publicKeyMultibase = `z${publicKeyBase58}`;
publicKeyMultibase = _multibaseEncode(
MULTICODEC_X25519_PUB_HEADER, base58btc.decode(publicKeyBase58));
}
if(privateKeyBase58) {
// prefix with `z` to indicate multi-base base58btc encoding
privateKeyMultibase = `z${privateKeyBase58}`;
privateKeyMultibase = _multibaseEncode(
MULTICODEC_X25519_PRIV_HEADER, base58btc.decode(privateKeyBase58));
}

@@ -126,6 +157,6 @@ return new X25519KeyAgreementKey2020({

if(!keyPair.publicKeyMultibase.startsWith('z')) {
if(!keyPair.publicKeyMultibase.startsWith(MULTIBASE_BASE58BTC_HEADER)) {
throw new TypeError(
// eslint-disable-next-line max-len
'Expecting "publicKeyMultibase" value to be multibase base58btc encoded (must start with "z").'
'Expecting "publicKeyMultibase" value to be multibase base58btc ' +
'encoded (must start with "z").'
);

@@ -141,6 +172,6 @@ }

if(keyPair.privateKeyMultibase) {
if(!keyPair.privateKeyMultibase.startsWith('z')) {
if(!keyPair.privateKeyMultibase.startsWith(MULTIBASE_BASE58BTC_HEADER)) {
throw new TypeError(
// eslint-disable-next-line max-len
'Expecting "privateKeyMultibase" value to be multibase base58btc encoded (must start with "z").'
'Expecting "privateKeyMultibase" value to be multibase base58btc ' +
'encoded (must start with "z").'
);

@@ -168,3 +199,4 @@ }

const edPubkeyBytes = _multibaseDecode({text: publicKeyMultibase});
const edPubkeyBytes =
_multibaseDecode(MULTICODEC_ED25519_PUB_HEADER, publicKeyMultibase);

@@ -178,3 +210,3 @@ // Converts a 32-byte Ed25519 public key into a 32-byte Curve25519 key

}
return _multibaseEncode({bytes: dhPubkeyBytes});
return _multibaseEncode(MULTICODEC_X25519_PUB_HEADER, dhPubkeyBytes);
}

@@ -194,3 +226,4 @@

const edPrivkeyBytes = _multibaseDecode({text: privateKeyMultibase});
const edPrivkeyBytes =
_multibaseDecode(MULTICODEC_ED25519_PRIV_HEADER, privateKeyMultibase);
// Converts a 64-byte Ed25519 secret key (or just the first 32-byte part of

@@ -203,3 +236,3 @@ // it, which is the secret value) into a 32-byte Curve25519 secret key

}
return _multibaseEncode({bytes: dhPrivkeyBytes});
return _multibaseEncode(MULTICODEC_X25519_PRIV_HEADER, dhPrivkeyBytes);
}

@@ -261,9 +294,4 @@

}
const publicKeyBytes = _multibaseDecode({text: publicKeyMultibase});
// X25519 cryptonyms are multicodec formatted values, specifically:
// (multicodec('x25519-pub') + key bytes)
const fingerprintBytes = _multicodecFormatFingerprint({publicKeyBytes});
const encodedFingerprint = _multibaseEncode({bytes: fingerprintBytes});
return encodedFingerprint;
return publicKeyMultibase;
}

@@ -281,14 +309,4 @@

static fromFingerprint({fingerprint} = {}) {
if(!fingerprint ||
!(typeof fingerprint === 'string' && fingerprint[0] === 'z')) {
throw new Error('`fingerprint` must be a multibase encoded string.');
}
const fingerprintBytes = _multibaseDecode({text: fingerprint});
const publicKeyBytes = _multicodecDecodeFingerprint({
bytes: fingerprintBytes
});
return new X25519KeyAgreementKey2020({
publicKeyMultibase: _multibaseEncode({bytes: publicKeyBytes})
publicKeyMultibase: fingerprint
});

@@ -309,8 +327,6 @@ }

async deriveSecret({publicKey}) {
const remotePublicKey = _multibaseDecode({
text: publicKey.publicKeyMultibase
});
const privateKey = _multibaseDecode({
text: this.privateKeyMultibase
});
const remotePublicKey = _multibaseDecode(
MULTICODEC_X25519_PUB_HEADER, publicKey.publicKeyMultibase);
const privateKey = _multibaseDecode(
MULTICODEC_X25519_PRIV_HEADER, this.privateKeyMultibase);

@@ -329,5 +345,3 @@ return deriveSecret({privateKey, remotePublicKey});

fingerprint() {
const {publicKeyMultibase} = this;
return X25519KeyAgreementKey2020
.fingerprintFromPublicKey({publicKeyMultibase});
return this.publicKeyMultibase;
}

@@ -351,29 +365,7 @@

// that it's base58btc multibase encoded
if(!(typeof fingerprint === 'string' && fingerprint[0] === 'z')) {
return {
// eslint-disable-next-line max-len
error: new Error('`fingerprint` must be a multibase base58btc encoded string (must start with a "z").'),
valid: false
};
if(!_isValidKeyHeader(fingerprint, MULTICODEC_X25519_PUB_HEADER)) {
throw new Error(
`"fingerprint" has invalid header bytes: "${fingerprint}".`);
}
let fingerprintBytes;
let fingerprintKeyBytes;
try {
fingerprintBytes = _multibaseDecode({text: fingerprint});
fingerprintKeyBytes = _multicodecDecodeFingerprint({
bytes: fingerprintBytes
});
} catch(e) {
return {valid: false, error: new Error('Error decoding fingerprint.')};
}
const publicKeyBytes = _multibaseDecode({text: this.publicKeyMultibase});
const valid = publicKeyBytes.toString() === fingerprintKeyBytes.toString();
if(!valid) {
return {
error: new Error('The fingerprint does not match the public key.'),
valid: false
};
}
return {valid: true};

@@ -390,67 +382,49 @@ }

/**
* Checks to see if the given value is a valid multibase encoded key.
*
* @param {Uint8Array} multibaseKey - The multibase-encoded key value.
* @param {Uint8Array} expectedHeader - The expected header for the key value.
* @returns {boolean} Returns true if the header is valid, false otherwise.
*/
function _isValidKeyHeader(multibaseKey, expectedHeader) {
if(!(typeof multibaseKey === 'string' &&
multibaseKey[0] === MULTIBASE_BASE58BTC_HEADER)) {
return false;
}
const keyBytes = base58btc.decode(multibaseKey.slice(1));
return expectedHeader.every((val, i) => keyBytes[i] === val);
}
/**
* Encodes a given Uint8Array to multibase-encoded string.
*
* @param {Uint8Array} header - Multicodec header to prepend to the bytes.
* @param {Uint8Array} bytes - Bytes to encode.
* @returns {string} Multibase-encoded string.
*/
function _multibaseEncode({bytes}) {
// prefix with `z` to indicate multi-base base58btc encoding
return `z${base58btc.encode(bytes)}`;
function _multibaseEncode(header, bytes) {
const mcBytes = new Uint8Array(header.length + bytes.length);
mcBytes.set(header);
mcBytes.set(bytes, header.length);
return MULTIBASE_BASE58BTC_HEADER + base58btc.encode(mcBytes);
}
/**
* Decodes a given multibase-encoded string.
* Decodes a given string as a multibase-encoded multicodec value.
*
* @param {Uint8Array} header - Expected header bytes for the multicodec value.
* @param {string} text - Multibase encoded string to decode.
* @returns {Uint8Array} Decoded bytes.
*/
function _multibaseDecode({text}) {
// drop the initial multibase 'z' prefix
return base58btc.decode(text.substr(1));
}
function _multibaseDecode(header, text) {
const mcValue = base58btc.decode(text.substr(1));
/**
* Returns raw fingerprint bytes, by adding a multicodec prefix for an
* X25519 public key.
*
* @see https://github.com/multiformats/multicodec/blob/master/table.csv
* 0xec is the value for X25519 public key
* 0x01 is from varint.encode(0xec) -> [0xec, 0x01]
* @see https://github.com/multiformats/unsigned-varint
*
* @param {object} [options={}] - Options hashmap.
* @param {Uint8Array} options.publicKeyBytes - Public key raw bytes.
*
* @returns {Uint8Array} Multicodec formatted public key fingerprint bytes.
*/
function _multicodecFormatFingerprint({publicKeyBytes} = {}) {
const fingerprintBytes = new Uint8Array(2 + publicKeyBytes.length);
fingerprintBytes[0] = 0xec;
fingerprintBytes[1] = 0x01;
fingerprintBytes.set(publicKeyBytes, 2);
return fingerprintBytes;
}
if(!header.every((val, i) => mcValue[i] === val)) {
throw new Error('Multibase value does not have expected header.');
}
/**
* Decodes a multicodec-formatted Uint8Array containing an x25519 public key.
*
* @see https://github.com/multiformats/multicodec/blob/master/table.csv
* 0xec is the value for X25519 public key
* 0x01 is from varint.encode(0xec) -> [0xec, 0x01]
* @see https://github.com/multiformats/unsigned-varint
*
* @param {object} [options={}] - Options hashmap.
* @param {Uint8Array} options.bytes - Key fingerprint decoded from multibase.
*
* @returns {{publicKeyBytes: Uint8Array}} The public key bytes (without the
* multicodec prefix).
*/
function _multicodecDecodeFingerprint({bytes} = {}) {
if(!(bytes && bytes[0] === 0xec && bytes[1] === 0x01)) {
// eslint-disable-next-line max-len
throw new Error('Expecting public key to be "x255519-pub" multicodec formatted [0xec, 0x01, <public key bytes>]');
}
// Remove the multicodec prefix
const publicKeyBytes = bytes.slice(2);
return publicKeyBytes;
return mcValue.slice(header.length);
}
{
"name": "@digitalbazaar/x25519-key-agreement-key-2020",
"version": "1.2.1",
"version": "2.0.0",
"description": "An X25519 (Curve25519) DH (Diffie-Hellman) key implementation to work with the X25519 2020 Crypto suite.",

@@ -38,3 +38,3 @@ "homepage": "https://github.com/digitalbazaar/x25519-key-agreement-key-2020",

"@babel/runtime": "^7.13.9",
"@digitalbazaar/ed25519-verification-key-2020": "^2.0.0",
"@digitalbazaar/ed25519-verification-key-2020": "^3.0.0",
"@digitalbazaar/x25519-key-agreement-key-2019": "^5.0.1",

@@ -41,0 +41,0 @@ "babel-loader": "^8.2.2",

@@ -69,7 +69,7 @@ # X25519KeyAgreementKey2020 _(@digitalbazaar/x25519-key-agreement-key-2020)_

{
"id": "did:example:1234#z6LShXSgPY6JKdbMmiLYaQ8JGjJFRrb4TsByj3dz5sSyQLUp",
"id": "did:example:1234#z6LSeRSE5Em5oJpwdk3NBaLVERBS332ULC7EQq5EtMsmXhsM",
"controller": "did:example:1234",
"type": "X25519KeyAgreementKey2020",
"publicKeyMultibase": "z6rGWsEHSEAscgKxn3kcLx95mai3wmG1pr4vJbQoSgxi4",
"privateKeyMultibase": "z8aAkJ9NcWKhSdQXvz1Eh2bDhptgSKAYn8ECvPVcAYjrp"
"publicKeyMultibase": "z6LSeRSE5Em5oJpwdk3NBaLVERBS332ULC7EQq5EtMsmXhsM",
"privateKeyMultibase": "z3weeMD56C1T347EmB6kYNS7trpQwjvtQCpCYRpqGz6mcemT"
}

@@ -85,6 +85,6 @@

{
"id": "did:example:1234#z6LShXSgPY6JKdbMmiLYaQ8JGjJFRrb4TsByj3dz5sSyQLUp",
"id": "did:example:1234#z6LSeRSE5Em5oJpwdk3NBaLVERBS332ULC7EQq5EtMsmXhsM",
"controller": "did:example:1234",
"type": "X25519KeyAgreementKey2020",
"publicKeyMultibase": "z6rGWsEHSEAscgKxn3kcLx95mai3wmG1pr4vJbQoSgxi4"
"publicKeyMultibase": "z6LSeRSE5Em5oJpwdk3NBaLVERBS332ULC7EQq5EtMsmXhsM"
}

@@ -100,7 +100,7 @@ ```

{
"id": "did:example:1234#z6LShXSgPY6JKdbMmiLYaQ8JGjJFRrb4TsByj3dz5sSyQLUp",
"id": "did:example:1234#z6LSeRSE5Em5oJpwdk3NBaLVERBS332ULC7EQq5EtMsmXhsM",
"controller": "did:example:1234",
"type": "X25519KeyAgreementKey2020",
"publicKeyMultibase": "z6rGWsEHSEAscgKxn3kcLx95mai3wmG1pr4vJbQoSgxi4",
"privateKeyMultibase": "z8aAkJ9NcWKhSdQXvz1Eh2bDhptgSKAYn8ECvPVcAYjrp"
"publicKeyMultibase": "z6LSeRSE5Em5oJpwdk3NBaLVERBS332ULC7EQq5EtMsmXhsM",
"privateKeyMultibase": "z3weeMD56C1T347EmB6kYNS7trpQwjvtQCpCYRpqGz6mcemT"
}

@@ -114,6 +114,6 @@ ```

const keyPair = await X25519KeyAgreementKey2020.from({
"id": "did:example:1234#z6LShXSgPY6JKdbMmiLYaQ8JGjJFRrb4TsByj3dz5sSyQLUp",
"id": "did:example:1234#z6LSeRSE5Em5oJpwdk3NBaLVERBS332ULC7EQq5EtMsmXhsM",
"controller": "did:example:1234",
"type": "X25519KeyAgreementKey2020",
"publicKeyMultibase": "z6rGWsEHSEAscgKxn3kcLx95mai3wmG1pr4vJbQoSgxi4"
"publicKeyMultibase": "z6LSeRSE5Em5oJpwdk3NBaLVERBS332ULC7EQq5EtMsmXhsM"
});

@@ -120,0 +120,0 @@ ```

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc