Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 11284x 11284x 11284x 11284x 11284x 11284x 11284x 11284x 11284x 11284x 11284x 11284x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 192x 192x 192x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 162567x 162567x 162567x 162567x 48396x 48396x 48396x 114171x 114171x 162567x 114171x 114171x 114171x 114171x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 77578x 77578x 77578x 77578x 77578x 77578x 77578x 77578x 77578x 77578x 77578x 77578x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 28577x 2800x 2800x 2800x 2800x 28577x | /**
* Add details about signing here.
*
* @_subsection: api/crypto:Signing [about-signing]
*/
import { secp256k1 } from "@noble/curves/secp256k1";
import {
concat, dataLength, getBytes, getBytesCopy, hexlify, toBeHex,
assertArgument
} from "../utils/index.js";
import { Signature } from "./signature.js";
import type { BytesLike } from "../utils/index.js";
import type { SignatureLike } from "./index.js";
/**
* A **SigningKey** provides high-level access to the elliptic curve
* cryptography (ECC) operations and key management.
*/
export class SigningKey {
#privateKey: string;
/**
* Creates a new **SigningKey** for %%privateKey%%.
*/
constructor(privateKey: BytesLike) {
assertArgument(dataLength(privateKey) === 32, "invalid private key", "privateKey", "[REDACTED]");
this.#privateKey = hexlify(privateKey);
}
/**
* The private key.
*/
get privateKey(): string { return this.#privateKey; }
/**
* The uncompressed public key.
*
* This will always begin with the prefix ``0x04`` and be 132
* characters long (the ``0x`` prefix and 130 hexadecimal nibbles).
*/
get publicKey(): string { return SigningKey.computePublicKey(this.#privateKey); }
/**
* The compressed public key.
*
* This will always begin with either the prefix ``0x02`` or ``0x03``
* and be 68 characters long (the ``0x`` prefix and 33 hexadecimal
* nibbles)
*/
get compressedPublicKey(): string { return SigningKey.computePublicKey(this.#privateKey, true); }
/**
* Return the signature of the signed %%digest%%.
*/
sign(digest: BytesLike): Signature {
assertArgument(dataLength(digest) === 32, "invalid digest length", "digest", digest);
const sig = secp256k1.sign(getBytesCopy(digest), getBytesCopy(this.#privateKey), {
lowS: true
});
return Signature.from({
r: toBeHex(sig.r, 32),
s: toBeHex(sig.s, 32),
v: (sig.recovery ? 0x1c: 0x1b)
});
}
/**
* Returns the [[link-wiki-ecdh]] shared secret between this
* private key and the %%other%% key.
*
* The %%other%% key may be any type of key, a raw public key,
* a compressed/uncompressed pubic key or aprivate key.
*
* Best practice is usually to use a cryptographic hash on the
* returned value before using it as a symetric secret.
*
* @example:
* sign1 = new SigningKey(id("some-secret-1"))
* sign2 = new SigningKey(id("some-secret-2"))
*
* // Notice that privA.computeSharedSecret(pubB)...
* sign1.computeSharedSecret(sign2.publicKey)
* //_result:
*
* // ...is equal to privB.computeSharedSecret(pubA).
* sign2.computeSharedSecret(sign1.publicKey)
* //_result:
*/
computeSharedSecret(other: BytesLike): string {
const pubKey = SigningKey.computePublicKey(other);
return hexlify(secp256k1.getSharedSecret(getBytesCopy(this.#privateKey), getBytes(pubKey), false));
}
/**
* Compute the public key for %%key%%, optionally %%compressed%%.
*
* The %%key%% may be any type of key, a raw public key, a
* compressed/uncompressed public key or private key.
*
* @example:
* sign = new SigningKey(id("some-secret"));
*
* // Compute the uncompressed public key for a private key
* SigningKey.computePublicKey(sign.privateKey)
* //_result:
*
* // Compute the compressed public key for a private key
* SigningKey.computePublicKey(sign.privateKey, true)
* //_result:
*
* // Compute the uncompressed public key
* SigningKey.computePublicKey(sign.publicKey, false);
* //_result:
*
* // Compute the Compressed a public key
* SigningKey.computePublicKey(sign.publicKey, true);
* //_result:
*/
static computePublicKey(key: BytesLike, compressed?: boolean): string {
let bytes = getBytes(key, "key");
// private key
if (bytes.length === 32) {
const pubKey = secp256k1.getPublicKey(bytes, !!compressed);
return hexlify(pubKey);
}
// raw public key; use uncompressed key with 0x04 prefix
if (bytes.length === 64) {
const pub = new Uint8Array(65);
pub[0] = 0x04;
pub.set(bytes, 1);
bytes = pub;
}
const point = secp256k1.ProjectivePoint.fromHex(bytes);
return hexlify(point.toRawBytes(compressed));
}
/**
* Returns the public key for the private key which produced the
* %%signature%% for the given %%digest%%.
*
* @example:
* key = new SigningKey(id("some-secret"))
* digest = id("hello world")
* sig = key.sign(digest)
*
* // Notice the signer public key...
* key.publicKey
* //_result:
*
* // ...is equal to the recovered public key
* SigningKey.recoverPublicKey(digest, sig)
* //_result:
*
*/
static recoverPublicKey(digest: BytesLike, signature: SignatureLike): string {
assertArgument(dataLength(digest) === 32, "invalid digest length", "digest", digest);
const sig = Signature.from(signature);
let secpSig = secp256k1.Signature.fromCompact(getBytesCopy(concat([ sig.r, sig.s ])));
secpSig = secpSig.addRecoveryBit(sig.yParity);
const pubKey = secpSig.recoverPublicKey(getBytesCopy(digest));
assertArgument(pubKey != null, "invalid signature for digest", "signature", signature);
return "0x" + pubKey.toHex(false);
}
/**
* Returns the point resulting from adding the ellipic curve points
* %%p0%% and %%p1%%.
*
* This is not a common function most developers should require, but
* can be useful for certain privacy-specific techniques.
*
* For example, it is used by [[HDNodeWallet]] to compute child
* addresses from parent public keys and chain codes.
*/
static addPoints(p0: BytesLike, p1: BytesLike, compressed?: boolean): string {
const pub0 = secp256k1.ProjectivePoint.fromHex(SigningKey.computePublicKey(p0).substring(2));
const pub1 = secp256k1.ProjectivePoint.fromHex(SigningKey.computePublicKey(p1).substring(2));
return "0x" + pub0.add(pub1).toHex(!!compressed)
}
}
|