-
Notifications
You must be signed in to change notification settings - Fork 91
Expand file tree
/
Copy pathec-utils.ts
More file actions
153 lines (145 loc) · 3.91 KB
/
ec-utils.ts
File metadata and controls
153 lines (145 loc) · 3.91 KB
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
import { decrypt, ECIES_CONFIG, encrypt, PublicKey } from 'eciesjs';
import {
computeAddress,
hexlify,
joinSignature,
recoverPublicKey,
SigningKey,
} from 'ethers/lib/utils';
import { ecDecryptLegacy } from './ec-utils-legacy';
/**
* Function to manage Elliptic-curve cryptography
*/
export {
ecDecrypt,
ecEncrypt,
getAddressFromPrivateKey,
getAddressFromPublicKey,
ecRecover,
ecSign,
};
ECIES_CONFIG.ellipticCurve = 'secp256k1';
ECIES_CONFIG.isEphemeralKeyCompressed = false;
ECIES_CONFIG.symmetricAlgorithm = 'aes-256-gcm';
ECIES_CONFIG.symmetricNonceLength = 16;
/**
* Function to derive the address from an EC private key
*
* @param privateKey the private key to derive
*
* @returns the address
*/
function getAddressFromPrivateKey(privateKey: string): string {
try {
if (!privateKey.match(/^0x/)) {
privateKey = `0x` + privateKey;
}
return computeAddress(hexlify(privateKey));
} catch (e) {
if (
e.message === 'private key length is invalid' ||
e.message === 'Expected private key to be an Uint8Array with length 32' ||
e.code === 'INVALID_ARGUMENT'
) {
throw new Error('The private key must be a string representing 32 bytes');
}
throw e;
}
}
/**
* Function to derive the address from an EC public key
*
* @param publicKey the public key to derive
*
* @returns the address
*/
function getAddressFromPublicKey(publicKey: string): string {
try {
const compressedKey = PublicKey.fromHex(publicKey).toHex(true);
return computeAddress(`0x${compressedKey}`);
} catch (e) {
if (e.code === 'INVALID_ARGUMENT' || e.message === 'second arg must be public key') {
throw new Error('The public key must be a string representing 64 bytes');
}
throw e;
}
}
/**
* Function ecSign data with ECDSA
*
* @param privateKey the private key used to sign the message
* @param data the data to sign
*
* @returns the signature
*/
function ecSign(privateKey: string, data: string): string {
try {
const signingKey = new SigningKey(privateKey);
return joinSignature(signingKey.signDigest(data));
} catch (e) {
if (e.code === 'INVALID_ARGUMENT') {
throw new Error('The private key must be a string representing 32 bytes');
}
throw e;
}
}
/**
* Function to recover address from a signature
*
* @param signature the signature
* @param data the data signed
*
* @returns the address
*/
function ecRecover(signature: string, data: string): string {
try {
return computeAddress(recoverPublicKey(data, signature));
} catch (e) {
if (e.code === 'INVALID_ARGUMENT') {
throw new Error('The signature must be a string representing 66 bytes');
}
throw e;
}
}
/**
* Function to encrypt data with a public key
*
* @param publicKey the public key to encrypt with
* @param data the data to encrypt
*
* @returns the encrypted data as a hex string
*/
function ecEncrypt(publicKey: string, data: string): string {
try {
return encrypt(publicKey, Buffer.from(data)).toString('hex');
} catch (e) {
if (e.message === 'second arg must be public key') {
throw new Error('The public key must be a string representing 64 bytes');
}
throw e;
}
}
/**
* Function to decrypt data with a public key
*
* @param privateKey the private key to decrypt with
* @param dataHex the hex data to decrypt
*
* @returns the decrypted data
*/
function ecDecrypt(privateKey: string, dataHex: string): string {
try {
return decrypt(privateKey.replace(/^0x/, ''), Buffer.from(dataHex, 'hex')).toString();
} catch (e) {
if (e.message.startsWith('invalid Point')) {
return ecDecryptLegacy(privateKey, dataHex);
}
if (e.message === 'Invalid private key') {
throw new Error('The private key must be a string representing 32 bytes');
}
if (e.message === 'second arg must be public key') {
throw new Error('The encrypted data is not well formatted');
}
throw e;
}
}