1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.createPair = void 0;
|
4 | const util_1 = require("@polkadot/util");
|
5 | const util_crypto_1 = require("@polkadot/util-crypto");
|
6 | const decode_js_1 = require("./decode.js");
|
7 | const encode_js_1 = require("./encode.js");
|
8 | const toJson_js_1 = require("./toJson.js");
|
9 | const SIG_TYPE_NONE = new Uint8Array();
|
10 | const TYPE_FROM_SEED = {
|
11 | ecdsa: util_crypto_1.secp256k1PairFromSeed,
|
12 | ed25519: util_crypto_1.ed25519PairFromSeed,
|
13 | ethereum: util_crypto_1.secp256k1PairFromSeed,
|
14 | sr25519: util_crypto_1.sr25519PairFromSeed
|
15 | };
|
16 | const TYPE_PREFIX = {
|
17 | ecdsa: new Uint8Array([2]),
|
18 | ed25519: new Uint8Array([0]),
|
19 | ethereum: new Uint8Array([2]),
|
20 | sr25519: new Uint8Array([1])
|
21 | };
|
22 | const TYPE_SIGNATURE = {
|
23 | ecdsa: (m, p) => (0, util_crypto_1.secp256k1Sign)(m, p, 'blake2'),
|
24 | ed25519: util_crypto_1.ed25519Sign,
|
25 | ethereum: (m, p) => (0, util_crypto_1.secp256k1Sign)(m, p, 'keccak'),
|
26 | sr25519: util_crypto_1.sr25519Sign
|
27 | };
|
28 | const TYPE_ADDRESS = {
|
29 | ecdsa: (p) => p.length > 32 ? (0, util_crypto_1.blake2AsU8a)(p) : p,
|
30 | ed25519: (p) => p,
|
31 | ethereum: (p) => p.length === 20 ? p : (0, util_crypto_1.keccakAsU8a)((0, util_crypto_1.secp256k1Expand)(p)),
|
32 | sr25519: (p) => p
|
33 | };
|
34 | function isLocked(secretKey) {
|
35 | return !secretKey || (0, util_1.u8aEmpty)(secretKey);
|
36 | }
|
37 | function vrfHash(proof, context, extra) {
|
38 | return (0, util_crypto_1.blake2AsU8a)((0, util_1.u8aConcat)(context || '', extra || '', proof));
|
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 | function createPair({ toSS58, type }, { publicKey, secretKey }, meta = {}, encoded = null, encTypes) {
|
72 | const decodePkcs8 = (passphrase, userEncoded) => {
|
73 | const decoded = (0, decode_js_1.decodePair)(passphrase, userEncoded || encoded, encTypes);
|
74 | if (decoded.secretKey.length === 64) {
|
75 | publicKey = decoded.publicKey;
|
76 | secretKey = decoded.secretKey;
|
77 | }
|
78 | else {
|
79 | const pair = TYPE_FROM_SEED[type](decoded.secretKey);
|
80 | publicKey = pair.publicKey;
|
81 | secretKey = pair.secretKey;
|
82 | }
|
83 | };
|
84 | const recode = (passphrase) => {
|
85 | isLocked(secretKey) && encoded && decodePkcs8(passphrase, encoded);
|
86 | encoded = (0, encode_js_1.encodePair)({ publicKey, secretKey }, passphrase);
|
87 | encTypes = undefined;
|
88 | return encoded;
|
89 | };
|
90 | const encodeAddress = () => {
|
91 | const raw = TYPE_ADDRESS[type](publicKey);
|
92 | return type === 'ethereum'
|
93 | ? (0, util_crypto_1.ethereumEncode)(raw)
|
94 | : toSS58(raw);
|
95 | };
|
96 | return {
|
97 | get address() {
|
98 | return encodeAddress();
|
99 | },
|
100 | get addressRaw() {
|
101 | const raw = TYPE_ADDRESS[type](publicKey);
|
102 | return type === 'ethereum'
|
103 | ? raw.slice(-20)
|
104 | : raw;
|
105 | },
|
106 | get isLocked() {
|
107 | return isLocked(secretKey);
|
108 | },
|
109 | get meta() {
|
110 | return meta;
|
111 | },
|
112 | get publicKey() {
|
113 | return publicKey;
|
114 | },
|
115 | get type() {
|
116 | return type;
|
117 | },
|
118 |
|
119 | decodePkcs8,
|
120 | derive: (suri, meta) => {
|
121 | if (type === 'ethereum') {
|
122 | throw new Error('Unable to derive on this keypair');
|
123 | }
|
124 | else if (isLocked(secretKey)) {
|
125 | throw new Error('Cannot derive on a locked keypair');
|
126 | }
|
127 | const { path } = (0, util_crypto_1.keyExtractPath)(suri);
|
128 | const derived = (0, util_crypto_1.keyFromPath)({ publicKey, secretKey }, path, type);
|
129 | return createPair({ toSS58, type }, derived, meta, null);
|
130 | },
|
131 | encodePkcs8: (passphrase) => {
|
132 | return recode(passphrase);
|
133 | },
|
134 | lock: () => {
|
135 | secretKey = new Uint8Array();
|
136 | },
|
137 | setMeta: (additional) => {
|
138 | meta = (0, util_1.objectSpread)({}, meta, additional);
|
139 | },
|
140 | sign: (message, options = {}) => {
|
141 | if (isLocked(secretKey)) {
|
142 | throw new Error('Cannot sign with a locked key pair');
|
143 | }
|
144 | return (0, util_1.u8aConcat)(options.withType
|
145 | ? TYPE_PREFIX[type]
|
146 | : SIG_TYPE_NONE, TYPE_SIGNATURE[type]((0, util_1.u8aToU8a)(message), { publicKey, secretKey }));
|
147 | },
|
148 | toJson: (passphrase) => {
|
149 |
|
150 |
|
151 |
|
152 | const address = ['ecdsa', 'ethereum'].includes(type)
|
153 | ? publicKey.length === 20
|
154 | ? (0, util_1.u8aToHex)(publicKey)
|
155 | : (0, util_1.u8aToHex)((0, util_crypto_1.secp256k1Compress)(publicKey))
|
156 | : encodeAddress();
|
157 | return (0, toJson_js_1.pairToJson)(type, { address, meta }, recode(passphrase), !!passphrase);
|
158 | },
|
159 | unlock: (passphrase) => {
|
160 | return decodePkcs8(passphrase);
|
161 | },
|
162 | verify: (message, signature, signerPublic) => {
|
163 | return (0, util_crypto_1.signatureVerify)(message, signature, TYPE_ADDRESS[type]((0, util_1.u8aToU8a)(signerPublic))).isValid;
|
164 | },
|
165 | vrfSign: (message, context, extra) => {
|
166 | if (isLocked(secretKey)) {
|
167 | throw new Error('Cannot sign with a locked key pair');
|
168 | }
|
169 | if (type === 'sr25519') {
|
170 | return (0, util_crypto_1.sr25519VrfSign)(message, { secretKey }, context, extra);
|
171 | }
|
172 | const proof = TYPE_SIGNATURE[type]((0, util_1.u8aToU8a)(message), { publicKey, secretKey });
|
173 | return (0, util_1.u8aConcat)(vrfHash(proof, context, extra), proof);
|
174 | },
|
175 | vrfVerify: (message, vrfResult, signerPublic, context, extra) => {
|
176 | if (type === 'sr25519') {
|
177 | return (0, util_crypto_1.sr25519VrfVerify)(message, vrfResult, publicKey, context, extra);
|
178 | }
|
179 | const result = (0, util_crypto_1.signatureVerify)(message, (0, util_1.u8aConcat)(TYPE_PREFIX[type], vrfResult.subarray(32)), TYPE_ADDRESS[type]((0, util_1.u8aToU8a)(signerPublic)));
|
180 | return result.isValid && (0, util_1.u8aEq)(vrfResult.subarray(0, 32), vrfHash(vrfResult.subarray(32), context, extra));
|
181 | }
|
182 | };
|
183 | }
|
184 | exports.createPair = createPair;
|