@theqrl/wallet.js 0.0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/package.json +15 -6
- package/src/dilithium.js +132 -150
- package/src/qrl/wordlist.js +4102 -374
- package/src/utils/mnemonic.js +88 -27
- package/src/index.js +0 -1
- package/src/qrl/index.js +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# wallet.js
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
[](https://codecov.io/gh/theQRL/wallet.js)
|
|
5
|
+
|
|
6
|
+
WIP helper library for QRL Dilithium wallet
|
package/package.json
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theqrl/wallet.js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "",
|
|
5
|
-
"main": "src/
|
|
5
|
+
"main": "src/dilithium.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "mocha",
|
|
8
8
|
"lint-check": "eslint 'src/**/*.js' 'test/**/*.js'",
|
|
9
|
-
"lint": "eslint --fix 'src/**/*.js' 'test/**/*.js'"
|
|
9
|
+
"lint": "eslint --fix 'src/**/*.js' 'test/**/*.js'",
|
|
10
|
+
"report-coverage": "c8 --reporter=text-lcov npm run test > coverage.lcov",
|
|
11
|
+
"coverage": "c8 npm run test"
|
|
10
12
|
},
|
|
11
13
|
"author": "QRL contributors <info@theqrl.org> (https://theqrl.org)",
|
|
12
14
|
"license": "MIT",
|
|
13
15
|
"dependencies": {
|
|
14
|
-
"@theqrl/dilithium5": "0.0.
|
|
16
|
+
"@theqrl/dilithium5": "^0.0.9",
|
|
15
17
|
"randombytes": "^2.1.0",
|
|
16
18
|
"sha3": "^2.1.4"
|
|
17
19
|
},
|
|
18
|
-
"type": "module",
|
|
19
20
|
"directories": {
|
|
20
21
|
"lib": "src",
|
|
21
22
|
"test": "test"
|
|
@@ -24,7 +25,15 @@
|
|
|
24
25
|
"src"
|
|
25
26
|
],
|
|
26
27
|
"devDependencies": {
|
|
28
|
+
"c8": "^7.13.0",
|
|
27
29
|
"chai": "^4.3.7",
|
|
28
|
-
"
|
|
30
|
+
"codecov": "^3.8.3",
|
|
31
|
+
"eslint": "^8.37.0",
|
|
32
|
+
"eslint-config-airbnb": "^19.0.4",
|
|
33
|
+
"eslint-config-prettier": "^8.8.0",
|
|
34
|
+
"eslint-plugin-import": "^2.27.5",
|
|
35
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
36
|
+
"mocha": "^10.2.0",
|
|
37
|
+
"prettier": "^2.8.7"
|
|
29
38
|
}
|
|
30
39
|
}
|
package/src/dilithium.js
CHANGED
|
@@ -1,176 +1,158 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
const { SHAKE } = require('sha3');
|
|
2
|
+
const randomBytes = require('randombytes');
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
cryptoSign,
|
|
6
|
+
cryptoSignKeypair,
|
|
7
|
+
cryptoSignOpen,
|
|
8
|
+
cryptoSignVerify,
|
|
9
|
+
// cryptoSignSignature,
|
|
10
|
+
CryptoPublicKeyBytes,
|
|
11
|
+
CryptoSecretKeyBytes,
|
|
12
|
+
// SeedBytes,
|
|
13
|
+
CryptoBytes,
|
|
14
|
+
} = require('@theqrl/dilithium5');
|
|
15
|
+
const { SeedBinToMnemonic } = require('./utils/mnemonic.js');
|
|
16
|
+
|
|
17
|
+
function getDilithiumDescriptor(address) {
|
|
18
|
+
/*
|
|
19
|
+
In case of Dilithium address, it doesn't have any choice of hashFunction,
|
|
20
|
+
height, addrFormatType. Thus keeping all those values to 0 and assigning
|
|
21
|
+
only signatureType in the descriptor.
|
|
22
|
+
*/
|
|
23
|
+
if (!address) {
|
|
24
|
+
throw new Error('Address is not defined');
|
|
25
|
+
}
|
|
26
|
+
return 2 << 4;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getDilithiumAddressFromPK(pk) {
|
|
30
|
+
const addressSize = 20;
|
|
31
|
+
const address = new Uint8Array(addressSize);
|
|
32
|
+
const descBytes = getDilithiumDescriptor(address);
|
|
33
|
+
address[0] = descBytes;
|
|
34
|
+
const hashedKey = new SHAKE(256);
|
|
35
|
+
hashedKey.update(Buffer.from(pk));
|
|
36
|
+
let hashedKeyDigest = hashedKey.digest({ buffer: Buffer.alloc(32), encoding: 'hex' });
|
|
37
|
+
hashedKeyDigest = hashedKeyDigest.slice(hashedKeyDigest.length - addressSize + 1);
|
|
38
|
+
for (let i = 0; i < hashedKeyDigest.length; i++) {
|
|
39
|
+
address[i + 1] = hashedKeyDigest[i];
|
|
40
|
+
}
|
|
41
|
+
return address;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
class Dilithium {
|
|
45
|
+
constructor(seed = null) {
|
|
46
|
+
this.pk = null;
|
|
47
|
+
this.sk = null;
|
|
48
|
+
this.seed = seed;
|
|
49
|
+
this.randomizedSigning = false;
|
|
50
|
+
if (this.seed === null) {
|
|
51
|
+
this.create();
|
|
52
|
+
} else {
|
|
53
|
+
this.fromSeed();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
10
56
|
|
|
11
|
-
|
|
57
|
+
create() {
|
|
58
|
+
const pk = new Uint8Array(CryptoPublicKeyBytes);
|
|
59
|
+
const sk = new Uint8Array(CryptoSecretKeyBytes);
|
|
60
|
+
const seed = randomBytes(48);
|
|
12
61
|
const hashedSeed = new SHAKE(256);
|
|
13
62
|
hashedSeed.update(seed);
|
|
14
|
-
|
|
15
|
-
|
|
63
|
+
const seedBuf = hashedSeed.digest({ buffer: Buffer.alloc(32) });
|
|
16
64
|
cryptoSignKeypair(seedBuf, pk, sk);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
GetAddress: new Function,
|
|
26
|
-
GetMnemonic: new Function,
|
|
27
|
-
GetHexSeed: new Function,
|
|
28
|
-
Seal: new Function,
|
|
29
|
-
Sign: new Function,
|
|
30
|
-
}
|
|
31
|
-
dilithium.GetPK = GetPK.bind(dilithium)
|
|
32
|
-
dilithium.GetSK = GetSK.bind(dilithium)
|
|
33
|
-
dilithium.GetSeed = GetSeed.bind(dilithium)
|
|
34
|
-
dilithium.GetHexSeed = GetHexSeed.bind(dilithium)
|
|
35
|
-
dilithium.GetMnemonic = GetMnemonic.bind(dilithium)
|
|
36
|
-
dilithium.Seal = Seal.bind(dilithium)
|
|
37
|
-
dilithium.Sign = Sign.bind(dilithium)
|
|
38
|
-
dilithium.GetAddress = GetAddress.bind(dilithium)
|
|
39
|
-
|
|
40
|
-
return dilithium
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function NewDilithiumFromSeed(seed) {
|
|
44
|
-
var pk = new Uint8Array(CryptoPublicKeyBytes);
|
|
45
|
-
var sk = new Uint8Array(CryptoSecretKeyBytes);
|
|
46
|
-
|
|
65
|
+
this.pk = pk;
|
|
66
|
+
this.sk = sk;
|
|
67
|
+
this.seed = seed;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fromSeed() {
|
|
71
|
+
const pk = new Uint8Array(CryptoPublicKeyBytes);
|
|
72
|
+
const sk = new Uint8Array(CryptoSecretKeyBytes);
|
|
47
73
|
const hashedSeed = new SHAKE(256);
|
|
48
|
-
hashedSeed.update(seed);
|
|
49
|
-
|
|
74
|
+
hashedSeed.update(this.seed);
|
|
75
|
+
const seedBuf = hashedSeed.digest({ buffer: Buffer.alloc(32) });
|
|
50
76
|
cryptoSignKeypair(seedBuf, pk, sk);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
seed: seed,
|
|
55
|
-
randomizedSigning: false,
|
|
56
|
-
GetPK: new Function,
|
|
57
|
-
GetSK: new Function,
|
|
58
|
-
GetSeed: new Function,
|
|
59
|
-
GetAddress: new Function,
|
|
60
|
-
GetMnemonic: new Function,
|
|
61
|
-
GetHexSeed: new Function,
|
|
62
|
-
Seal: new Function,
|
|
63
|
-
Sign: new Function,
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
dilithium.GetPK = GetPK.bind(dilithium)
|
|
67
|
-
dilithium.GetSK = GetSK.bind(dilithium)
|
|
68
|
-
dilithium.GetSeed = GetSeed.bind(dilithium)
|
|
69
|
-
dilithium.GetHexSeed = GetHexSeed.bind(dilithium)
|
|
70
|
-
dilithium.GetMnemonic = GetMnemonic.bind(dilithium)
|
|
71
|
-
dilithium.Seal = Seal.bind(dilithium)
|
|
72
|
-
dilithium.Sign = Sign.bind(dilithium)
|
|
73
|
-
dilithium.GetAddress = GetAddress.bind(dilithium)
|
|
74
|
-
|
|
75
|
-
return dilithium
|
|
76
|
-
}
|
|
77
|
+
this.pk = pk;
|
|
78
|
+
this.sk = sk;
|
|
79
|
+
}
|
|
77
80
|
|
|
78
|
-
|
|
79
|
-
return this.pk
|
|
80
|
-
}
|
|
81
|
+
getPK() {
|
|
82
|
+
return this.pk;
|
|
83
|
+
}
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
return this.sk
|
|
84
|
-
}
|
|
85
|
+
getSK() {
|
|
86
|
+
return this.sk;
|
|
87
|
+
}
|
|
85
88
|
|
|
86
|
-
|
|
87
|
-
return this.seed
|
|
88
|
-
}
|
|
89
|
+
getSeed() {
|
|
90
|
+
return this.seed;
|
|
91
|
+
}
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
return
|
|
92
|
-
}
|
|
93
|
+
getHexSeed() {
|
|
94
|
+
return `0x${this.seed.toString('hex')}`;
|
|
95
|
+
}
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
return SeedBinToMnemonic(this.seed)
|
|
96
|
-
}
|
|
97
|
+
getMnemonic() {
|
|
98
|
+
return SeedBinToMnemonic(this.seed);
|
|
99
|
+
}
|
|
97
100
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
101
|
+
getAddress() {
|
|
102
|
+
return getDilithiumAddressFromPK(this.pk);
|
|
103
|
+
}
|
|
102
104
|
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
var signature = new Uint8Array(CryptoBytes)
|
|
108
|
-
signature = sm.slice(0, CryptoBytes)
|
|
109
|
-
return signature
|
|
110
|
-
}
|
|
105
|
+
// Seal the message, returns signature attached with message.
|
|
106
|
+
seal(message) {
|
|
107
|
+
return cryptoSign(message, this.sk, this.randomizedSigning);
|
|
108
|
+
}
|
|
111
109
|
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
// Sign the message, and return a detached signature. Detached signatures are
|
|
111
|
+
// variable sized, but never larger than SIG_SIZE_PACKED.
|
|
112
|
+
sign(message) {
|
|
113
|
+
const sm = cryptoSign(message, this.sk);
|
|
114
|
+
let signature = new Uint8Array(CryptoBytes);
|
|
115
|
+
signature = sm.slice(0, CryptoBytes);
|
|
116
|
+
return signature;
|
|
117
|
+
}
|
|
114
118
|
}
|
|
115
119
|
|
|
116
120
|
// Open the sealed message m. Returns the original message sealed with signature.
|
|
117
121
|
// In case the signature is invalid, nil is returned.
|
|
118
|
-
function
|
|
119
|
-
|
|
122
|
+
function openMessage(signatureMessage, pk) {
|
|
123
|
+
return cryptoSignOpen(signatureMessage, pk);
|
|
120
124
|
}
|
|
121
125
|
|
|
122
|
-
function
|
|
123
|
-
|
|
126
|
+
function verifyMessage(message, signature, pk) {
|
|
127
|
+
return cryptoSignVerify(signature, message, pk);
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
// ExtractMessage extracts message from Signature attached with message.
|
|
127
|
-
function
|
|
128
|
-
|
|
131
|
+
function extractMessage(signatureMessage) {
|
|
132
|
+
return signatureMessage.slice(CryptoBytes, signatureMessage.length);
|
|
129
133
|
}
|
|
130
134
|
|
|
131
135
|
// ExtractSignature extracts signature from Signature attached with message.
|
|
132
|
-
function
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
for (let i = 0; i < hashedKeyDigest.length; i++) {
|
|
156
|
-
address[i + 1] = hashedKeyDigest[i]
|
|
157
|
-
}
|
|
158
|
-
return address
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function IsValidDilithiumAddress(address) {
|
|
162
|
-
let d = GetDilithiumDescriptor()
|
|
163
|
-
if (address[0] != d) {
|
|
164
|
-
return false
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// TODO: Add checksum
|
|
168
|
-
return true
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
let DilithiumWallet;
|
|
172
|
-
|
|
173
|
-
export default DilithiumWallet = {
|
|
174
|
-
New, NewDilithiumFromSeed, Open, Verify, ExtractMessage, ExtractSignature, GetDilithiumDescriptor, GetDilithiumAddressFromPK, IsValidDilithiumAddress
|
|
175
|
-
}
|
|
176
|
-
|
|
136
|
+
function extractSignature(signatureMessage) {
|
|
137
|
+
return signatureMessage.slice(0, CryptoBytes);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function isValidDilithiumAddress(address) {
|
|
141
|
+
const d = getDilithiumDescriptor(address);
|
|
142
|
+
if (address[0] !== d) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
// TODO: Add checksum
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = {
|
|
150
|
+
Dilithium,
|
|
151
|
+
getDilithiumAddressFromPK,
|
|
152
|
+
getDilithiumDescriptor,
|
|
153
|
+
openMessage,
|
|
154
|
+
verifyMessage,
|
|
155
|
+
extractMessage,
|
|
156
|
+
extractSignature,
|
|
157
|
+
isValidDilithiumAddress,
|
|
158
|
+
};
|