chore: update to version 14.0.11 and align website URLs

This commit is contained in:
2026-01-11 11:34:13 +03:00
parent ef74383349
commit 19c8d69bd8
1499 changed files with 53633 additions and 89 deletions
+12
View File
@@ -0,0 +1,12 @@
import type { EncryptedJsonEncoding } from '@pezkuwi/util-crypto/types';
/**
* Decode a pair, taking into account the generation-specific formats and headers
*
* For divisor/headers, don't rely on the magic being static. These will
* change between generations, aka with the long-awaited 4th generation
* of the format. The external decode interface is the only way to use and decode these.
**/
export declare function decodePair(passphrase?: string, encrypted?: Uint8Array | null, _encType?: EncryptedJsonEncoding | EncryptedJsonEncoding[]): {
publicKey: Uint8Array;
secretKey: Uint8Array;
};
+42
View File
@@ -0,0 +1,42 @@
import { u8aEq } from '@pezkuwi/util';
import { jsonDecryptData } from '@pezkuwi/util-crypto';
import { PAIR_DIV, PAIR_HDR, PUB_LENGTH, SEC_LENGTH, SEED_LENGTH } from './defaults.js';
const SEED_OFFSET = PAIR_HDR.length;
/**
* Decode a pair, taking into account the generation-specific formats and headers
*
* For divisor/headers, don't rely on the magic being static. These will
* change between generations, aka with the long-awaited 4th generation
* of the format. The external decode interface is the only way to use and decode these.
**/
export function decodePair(passphrase, encrypted, _encType) {
const encType = Array.isArray(_encType) || _encType === undefined
? _encType
: [_encType];
const decrypted = jsonDecryptData(encrypted, passphrase, encType);
const header = decrypted.subarray(0, PAIR_HDR.length);
// check the start header (generations 1-3)
if (!u8aEq(header, PAIR_HDR)) {
throw new Error('Invalid encoding header found in body');
}
// setup for generation 3 format
let secretKey = decrypted.subarray(SEED_OFFSET, SEED_OFFSET + SEC_LENGTH);
let divOffset = SEED_OFFSET + SEC_LENGTH;
let divider = decrypted.subarray(divOffset, divOffset + PAIR_DIV.length);
// old-style (generation 1 & 2), we have the seed here
if (!u8aEq(divider, PAIR_DIV)) {
divOffset = SEED_OFFSET + SEED_LENGTH;
secretKey = decrypted.subarray(SEED_OFFSET, divOffset);
divider = decrypted.subarray(divOffset, divOffset + PAIR_DIV.length);
// check the divisior at this point (already checked for generation 3)
if (!u8aEq(divider, PAIR_DIV)) {
throw new Error('Invalid encoding divider found in body');
}
}
const pubOffset = divOffset + PAIR_DIV.length;
const publicKey = decrypted.subarray(pubOffset, pubOffset + PUB_LENGTH);
return {
publicKey,
secretKey
};
}
+12
View File
@@ -0,0 +1,12 @@
/** public/secret section divider (generation 1-3, will change in 4, don't rely on value) */
export declare const PAIR_DIV: Uint8Array;
/** public/secret start block (generation 1-3, will change in 4, don't rely on value) */
export declare const PAIR_HDR: Uint8Array;
/** length of a public key */
export declare const PUB_LENGTH = 32;
/** length of a salt */
export declare const SALT_LENGTH = 32;
/** length of a secret key */
export declare const SEC_LENGTH = 64;
/** length of a user-input seed */
export declare const SEED_LENGTH = 32;
+12
View File
@@ -0,0 +1,12 @@
/** public/secret section divider (generation 1-3, will change in 4, don't rely on value) */
export const PAIR_DIV = new Uint8Array([161, 35, 3, 33, 0]);
/** public/secret start block (generation 1-3, will change in 4, don't rely on value) */
export const PAIR_HDR = new Uint8Array([48, 83, 2, 1, 1, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32]);
/** length of a public key */
export const PUB_LENGTH = 32;
/** length of a salt */
export const SALT_LENGTH = 32;
/** length of a secret key */
export const SEC_LENGTH = 64;
/** length of a user-input seed */
export const SEED_LENGTH = 32;
+5
View File
@@ -0,0 +1,5 @@
import type { PairInfo } from './types.js';
/**
* Encode a pair with the latest generation format (generation 3)
**/
export declare function encodePair({ publicKey, secretKey }: PairInfo, passphrase?: string): Uint8Array;
+19
View File
@@ -0,0 +1,19 @@
import { u8aConcat } from '@pezkuwi/util';
import { naclEncrypt, scryptEncode, scryptToU8a } from '@pezkuwi/util-crypto';
import { PAIR_DIV, PAIR_HDR } from './defaults.js';
/**
* Encode a pair with the latest generation format (generation 3)
**/
export function encodePair({ publicKey, secretKey }, passphrase) {
if (!secretKey) {
throw new Error('Expected a valid secretKey to be passed to encode');
}
const encoded = u8aConcat(PAIR_HDR, secretKey, PAIR_DIV, publicKey);
if (!passphrase) {
return encoded;
}
// this is only for generation 3 (previous generations are only handled in decoding)
const { params, password, salt } = scryptEncode(passphrase);
const { encrypted, nonce } = naclEncrypt(encoded, password.subarray(0, 32));
return u8aConcat(scryptToU8a(salt, params), nonce, encrypted);
}
+40
View File
@@ -0,0 +1,40 @@
import type { EncryptedJsonEncoding, KeypairType } from '@pezkuwi/util-crypto/types';
import type { KeyringPair, KeyringPair$Meta } from '../types.js';
import type { PairInfo } from './types.js';
interface Setup {
toSS58: (publicKey: Uint8Array) => string;
type: KeypairType;
}
/**
* @name createPair
* @summary Creates a keyring pair object
* @description Creates a keyring pair object with provided account public key, metadata, and encoded arguments.
* The keyring pair stores the account state including the encoded address and associated metadata.
*
* It has properties whose values are functions that may be called to perform account actions:
*
* - `address` function retrieves the address associated with the account.
* - `decodedPkcs8` function is called with the account passphrase and account encoded public key.
* It decodes the encoded public key using the passphrase provided to obtain the decoded account public key
* and associated secret key that are then available in memory, and changes the account address stored in the
* state of the pair to correspond to the address of the decoded public key.
* - `encodePkcs8` function when provided with the correct passphrase associated with the account pair
* and when the secret key is in memory (when the account pair is not locked) it returns an encoded
* public key of the account.
* - `meta` is the metadata that is stored in the state of the pair, either when it was originally
* created or set via `setMeta`.
* - `publicKey` returns the public key stored in memory for the pair.
* - `sign` may be used to return a signature by signing a provided message with the secret
* key (if it is in memory) using Nacl.
* - `toJson` calls another `toJson` function and provides the state of the pair,
* it generates arguments to be passed to the other `toJson` function including an encoded public key of the account
* that it generates using the secret key from memory (if it has been made available in memory)
* and the optionally provided passphrase argument. It passes a third boolean argument to `toJson`
* indicating whether the public key has been encoded or not (if a passphrase argument was provided then it is encoded).
* The `toJson` function that it calls returns a JSON object with properties including the `address`
* and `meta` that are assigned with the values stored in the corresponding state variables of the account pair,
* an `encoded` property that is assigned with the encoded public key in hex format, and an `encoding`
* property that indicates whether the public key value of the `encoded` property is encoded or not.
*/
export declare function createPair({ toSS58, type }: Setup, { publicKey, secretKey }: PairInfo, meta?: KeyringPair$Meta, encoded?: Uint8Array | null, encTypes?: EncryptedJsonEncoding[]): KeyringPair;
export {};
+180
View File
@@ -0,0 +1,180 @@
import { objectSpread, u8aConcat, u8aEmpty, u8aEq, u8aToHex, u8aToU8a } from '@pezkuwi/util';
import { blake2AsU8a, ed25519PairFromSeed as ed25519FromSeed, ed25519Sign, ethereumEncode, keccakAsU8a, keyExtractPath, keyFromPath, secp256k1Compress, secp256k1Expand, secp256k1PairFromSeed as secp256k1FromSeed, secp256k1Sign, signatureVerify, sr25519PairFromSeed as sr25519FromSeed, sr25519Sign, sr25519VrfSign, sr25519VrfVerify } from '@pezkuwi/util-crypto';
import { decodePair } from './decode.js';
import { encodePair } from './encode.js';
import { pairToJson } from './toJson.js';
const SIG_TYPE_NONE = new Uint8Array();
const TYPE_FROM_SEED = {
ecdsa: secp256k1FromSeed,
ed25519: ed25519FromSeed,
ethereum: secp256k1FromSeed,
sr25519: sr25519FromSeed
};
const TYPE_PREFIX = {
ecdsa: new Uint8Array([2]),
ed25519: new Uint8Array([0]),
ethereum: new Uint8Array([2]),
sr25519: new Uint8Array([1])
};
const TYPE_SIGNATURE = {
ecdsa: (m, p) => secp256k1Sign(m, p, 'blake2'),
ed25519: ed25519Sign,
ethereum: (m, p) => secp256k1Sign(m, p, 'keccak'),
sr25519: sr25519Sign
};
const TYPE_ADDRESS = {
ecdsa: (p) => p.length > 32 ? blake2AsU8a(p) : p,
ed25519: (p) => p,
ethereum: (p) => p.length === 20 ? p : keccakAsU8a(secp256k1Expand(p)),
sr25519: (p) => p
};
function isLocked(secretKey) {
return !secretKey || u8aEmpty(secretKey);
}
function vrfHash(proof, context, extra) {
return blake2AsU8a(u8aConcat(context || '', extra || '', proof));
}
/**
* @name createPair
* @summary Creates a keyring pair object
* @description Creates a keyring pair object with provided account public key, metadata, and encoded arguments.
* The keyring pair stores the account state including the encoded address and associated metadata.
*
* It has properties whose values are functions that may be called to perform account actions:
*
* - `address` function retrieves the address associated with the account.
* - `decodedPkcs8` function is called with the account passphrase and account encoded public key.
* It decodes the encoded public key using the passphrase provided to obtain the decoded account public key
* and associated secret key that are then available in memory, and changes the account address stored in the
* state of the pair to correspond to the address of the decoded public key.
* - `encodePkcs8` function when provided with the correct passphrase associated with the account pair
* and when the secret key is in memory (when the account pair is not locked) it returns an encoded
* public key of the account.
* - `meta` is the metadata that is stored in the state of the pair, either when it was originally
* created or set via `setMeta`.
* - `publicKey` returns the public key stored in memory for the pair.
* - `sign` may be used to return a signature by signing a provided message with the secret
* key (if it is in memory) using Nacl.
* - `toJson` calls another `toJson` function and provides the state of the pair,
* it generates arguments to be passed to the other `toJson` function including an encoded public key of the account
* that it generates using the secret key from memory (if it has been made available in memory)
* and the optionally provided passphrase argument. It passes a third boolean argument to `toJson`
* indicating whether the public key has been encoded or not (if a passphrase argument was provided then it is encoded).
* The `toJson` function that it calls returns a JSON object with properties including the `address`
* and `meta` that are assigned with the values stored in the corresponding state variables of the account pair,
* an `encoded` property that is assigned with the encoded public key in hex format, and an `encoding`
* property that indicates whether the public key value of the `encoded` property is encoded or not.
*/
export function createPair({ toSS58, type }, { publicKey, secretKey }, meta = {}, encoded = null, encTypes) {
const decodePkcs8 = (passphrase, userEncoded) => {
const decoded = decodePair(passphrase, userEncoded || encoded, encTypes);
if (decoded.secretKey.length === 64) {
publicKey = decoded.publicKey;
secretKey = decoded.secretKey;
}
else {
const pair = TYPE_FROM_SEED[type](decoded.secretKey);
publicKey = pair.publicKey;
secretKey = pair.secretKey;
}
};
const recode = (passphrase) => {
isLocked(secretKey) && encoded && decodePkcs8(passphrase, encoded);
encoded = encodePair({ publicKey, secretKey }, passphrase); // re-encode, latest version
encTypes = undefined; // swap to defaults, latest version follows
return encoded;
};
const encodeAddress = () => {
const raw = TYPE_ADDRESS[type](publicKey);
return type === 'ethereum'
? ethereumEncode(raw)
: toSS58(raw);
};
return {
get address() {
return encodeAddress();
},
get addressRaw() {
const raw = TYPE_ADDRESS[type](publicKey);
return type === 'ethereum'
? raw.slice(-20)
: raw;
},
get isLocked() {
return isLocked(secretKey);
},
get meta() {
return meta;
},
get publicKey() {
return publicKey;
},
get type() {
return type;
},
// eslint-disable-next-line sort-keys
decodePkcs8,
derive: (suri, meta) => {
if (type === 'ethereum') {
throw new Error('Unable to derive on this keypair');
}
else if (isLocked(secretKey)) {
throw new Error('Cannot derive on a locked keypair');
}
const { path } = keyExtractPath(suri);
const derived = keyFromPath({ publicKey, secretKey }, path, type);
return createPair({ toSS58, type }, derived, meta, null);
},
encodePkcs8: (passphrase) => {
return recode(passphrase);
},
lock: () => {
secretKey = new Uint8Array();
},
setMeta: (additional) => {
meta = objectSpread({}, meta, additional);
},
sign: (message, options = {}) => {
if (isLocked(secretKey)) {
throw new Error('Cannot sign with a locked key pair');
}
return u8aConcat(options.withType
? TYPE_PREFIX[type]
: SIG_TYPE_NONE, TYPE_SIGNATURE[type](u8aToU8a(message), { publicKey, secretKey }));
},
toJson: (passphrase) => {
// NOTE: For ecdsa and ethereum, the publicKey cannot be extracted from the address. For these
// pass the hex-encoded publicKey through to the address portion of the JSON (before decoding)
// unless the publicKey is already an address
const address = ['ecdsa', 'ethereum'].includes(type)
? publicKey.length === 20
? u8aToHex(publicKey)
: u8aToHex(secp256k1Compress(publicKey))
: encodeAddress();
return pairToJson(type, { address, meta }, recode(passphrase), !!passphrase);
},
unlock: (passphrase) => {
return decodePkcs8(passphrase);
},
verify: (message, signature, signerPublic) => {
return signatureVerify(message, signature, TYPE_ADDRESS[type](u8aToU8a(signerPublic))).isValid;
},
vrfSign: (message, context, extra) => {
if (isLocked(secretKey)) {
throw new Error('Cannot sign with a locked key pair');
}
if (type === 'sr25519') {
return sr25519VrfSign(message, { secretKey }, context, extra);
}
const proof = TYPE_SIGNATURE[type](u8aToU8a(message), { publicKey, secretKey });
return u8aConcat(vrfHash(proof, context, extra), proof);
},
vrfVerify: (message, vrfResult, signerPublic, context, extra) => {
if (type === 'sr25519') {
return sr25519VrfVerify(message, vrfResult, publicKey, context, extra);
}
const result = signatureVerify(message, u8aConcat(TYPE_PREFIX[type], vrfResult.subarray(32)), TYPE_ADDRESS[type](u8aToU8a(signerPublic)));
return result.isValid && u8aEq(vrfResult.subarray(0, 32), vrfHash(vrfResult.subarray(32), context, extra));
}
};
}
+2
View File
@@ -0,0 +1,2 @@
import type { KeyringPair } from '../types.js';
export declare function nobody(): KeyringPair;
+40
View File
@@ -0,0 +1,40 @@
const publicKey = new Uint8Array(32);
const address = '5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM';
const meta = {
isTesting: true,
name: 'nobody'
};
const json = {
address,
encoded: '',
encoding: {
content: ['pkcs8', 'ed25519'],
type: 'none',
version: '0'
},
meta
};
const pair = {
address,
addressRaw: publicKey,
decodePkcs8: (_passphrase, _encoded) => undefined,
derive: (_suri, _meta) => pair,
encodePkcs8: (_passphrase) => new Uint8Array(0),
isLocked: true,
lock: () => {
// no locking, it is always locked
},
meta,
publicKey,
setMeta: (_meta) => undefined,
sign: (_message) => new Uint8Array(64),
toJson: (_passphrase) => json,
type: 'ed25519',
unlock: (_passphrase) => undefined,
verify: (_message, _signature) => false,
vrfSign: (_message, _context, _extra) => new Uint8Array(96),
vrfVerify: (_message, _vrfResult, _context, _extra) => false
};
export function nobody() {
return pair;
}
+8
View File
@@ -0,0 +1,8 @@
import type { KeypairType } from '@pezkuwi/util-crypto/types';
import type { KeyringPair$Json, KeyringPair$Meta } from '../types.js';
interface PairStateJson {
address: string;
meta: KeyringPair$Meta;
}
export declare function pairToJson(type: KeypairType, { address, meta }: PairStateJson, encoded: Uint8Array, isEncrypted: boolean): KeyringPair$Json;
export {};
+8
View File
@@ -0,0 +1,8 @@
import { objectSpread } from '@pezkuwi/util';
import { jsonEncryptFormat } from '@pezkuwi/util-crypto';
export function pairToJson(type, { address, meta }, encoded, isEncrypted) {
return objectSpread(jsonEncryptFormat(encoded, ['pkcs8', type], isEncrypted), {
address,
meta
});
}
+5
View File
@@ -0,0 +1,5 @@
export interface PairInfo {
publicKey: Uint8Array;
secretKey?: Uint8Array | undefined;
seed?: Uint8Array | null;
}
+1
View File
@@ -0,0 +1 @@
export {};