-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
84 lines (68 loc) · 2.06 KB
/
index.js
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
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const crypto = require('crypto')
const array = length => Array.from({ length })
const readBytes = (buf, read, from = 0) => buf.slice(from, from + read)
const bitsForByte = byte => {
return [128, 64, 32, 16, 8, 4, 2, 1].map(pos => {
return byte & pos ? 1 : 0
})
}
const bitsForBuffer = buffer => array(buffer.length).reduce((bits, _, idx) => {
return bits.concat(bitsForByte(buffer[idx]))
}, [])
const getSizes = hash => {
const buf = hash(Buffer.alloc(0))
return {
bytes: buf.length,
bits: buf.length * 8
}
}
function lamport (hash) {
const { bits, bytes } = getSizes(hash)
const readChunk = (buf, idx) => readBytes(buf, bytes, bytes * idx)
const keys = () => {
const privateKey = [0, 1].map(() =>
crypto.randomBytes(bits * bytes)
)
const publicKey = privateKey.map(privateKeyHalf => {
return array(bits).reduce((publicKeyHalf, _, idx) => {
return Buffer.concat([publicKeyHalf, hash(
readChunk(privateKeyHalf, idx)
)], (idx + 1) * bytes)
}, Buffer.alloc(0))
})
return {
publicKey,
privateKey
}
}
const sign = (input, key) => {
const msg = hash(input)
return bitsForBuffer(msg).reduce((sig, bit, idx) => {
return Buffer.concat([sig,
readChunk(key[bit], idx)
], (idx + 1) * bytes)
}, Buffer.alloc(0))
}
const verify = (input, sig, key) => {
const msg = hash(input)
return bitsForBuffer(msg).reduce((valid, bit, idx) => {
return valid && readChunk(key[bit], idx).equals(
hash(readChunk(sig, idx))
)
}, true)
}
return {
keys,
verify,
sign
}
}
exports = module.exports = lamport
const sha256 = msg => crypto.createHash('sha256').update(msg).digest()
const lamportSHA256 = lamport(sha256)
exports.keys = lamportSHA256.keys
exports.sign = lamportSHA256.sign
exports.verify = lamportSHA256.verify