hypercore-sign-lib
Advanced tools
+156
-68
@@ -13,66 +13,8 @@ const c = require('compact-encoding') | ||
| const publicKey = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES) | ||
| const salt = Buffer.alloc(32) | ||
| const checkSum = Buffer.alloc(sodium.crypto_generichash_BYTES) | ||
| const secretKey = sodium.sodium_malloc(sodium.crypto_sign_SECRETKEYBYTES) | ||
| const kdfOutput = sodium.sodium_malloc(id.byteLength + secretKey.byteLength + checkSum.byteLength) | ||
| const params = { | ||
| ops: sodium.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE, | ||
| mem: sodium.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE | ||
| } | ||
| sodium.randombytes_buf(id) | ||
| sodium.randombytes_buf(salt) | ||
| sodium.crypto_sign_keypair(publicKey, secretKey) | ||
| const checkSumData = c.encode(LabelledKey, { id, secretKey }) | ||
| sodium.crypto_generichash(checkSum, checkSumData) | ||
| free(checkSumData) | ||
| const payload = c.encode(KeyDescriptor, { | ||
| id, | ||
| secretKey, | ||
| checkSum | ||
| }) | ||
| free(secretKey) | ||
| sodium.sodium_mprotect_readwrite(pwd) | ||
| try { | ||
| await sodium.crypto_pwhash_scryptsalsa208sha256_async( | ||
| kdfOutput, | ||
| pwd, | ||
| salt, | ||
| params.ops, | ||
| params.mem | ||
| ) | ||
| } finally { | ||
| free(pwd) | ||
| } | ||
| try { | ||
| xor(payload, kdfOutput) | ||
| } finally { | ||
| free(kdfOutput) | ||
| } | ||
| const encrypted = c.encode(EncryptedKey, { | ||
| version: MAX_KEY_VERSION, | ||
| params, | ||
| salt, | ||
| payload, | ||
| publicKey | ||
| }) | ||
| free(payload) | ||
| return { | ||
| id, | ||
| publicKey, | ||
| secretKey: encrypted | ||
| } | ||
| return store(id, secretKey, publicKey, pwd) | ||
| } | ||
@@ -197,18 +139,152 @@ | ||
| function free(buffer) { | ||
| if (buffer.secure) sodium.sodium_mprotect_readwrite(buffer) | ||
| sodium.sodium_memzero(buffer) | ||
| sodium.sodium_free(buffer) | ||
| async function migrate(keyBuffer, pwd) { | ||
| let key = null | ||
| try { | ||
| key = c.decode(EncryptedKey, keyBuffer) | ||
| } catch { | ||
| free(pwd) | ||
| throw new Error('Invalid key') | ||
| } | ||
| const { version, params, salt, payload } = key | ||
| if (version > MAX_KEY_VERSION) { | ||
| free(pwd) | ||
| throw new Error('Key version not supported, please update') | ||
| } | ||
| if (version > COMPAT_VERSION) { | ||
| free(pwd) | ||
| return null | ||
| } | ||
| const kdfOutput = sodium.sodium_malloc(payload.byteLength) | ||
| const publicKey = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES) | ||
| sodium.sodium_mprotect_readwrite(pwd) | ||
| sodium.sodium_mprotect_readwrite(kdfOutput) | ||
| try { | ||
| await sodium.crypto_pwhash_scryptsalsa208sha256_async( | ||
| kdfOutput, | ||
| pwd, | ||
| salt, | ||
| params.ops, | ||
| params.mem | ||
| ) | ||
| xor(payload, kdfOutput) | ||
| } finally { | ||
| free(kdfOutput) | ||
| } | ||
| const { id, secretKey, checkSum } = c.decode(KeyDescriptor, payload) | ||
| const checkAgainst = Buffer.alloc(sodium.crypto_generichash_BYTES) | ||
| const checkSumData = c.encode(LabelledKey, { id, secretKey }) | ||
| try { | ||
| sodium.crypto_generichash(checkAgainst, checkSumData) | ||
| if (Buffer.compare(checkAgainst, checkSum) !== 0) { | ||
| throw new Error('Key decryption failed') | ||
| } | ||
| } catch (err) { | ||
| free(checkSumData) | ||
| free(secretKey) | ||
| free(payload) | ||
| throw err | ||
| } | ||
| sodium.crypto_sign_ed25519_sk_to_pk(publicKey, secretKey) | ||
| return store(id, secretKey, publicKey, pwd) | ||
| } | ||
| function xor(a, b) { | ||
| if (a.byteLength !== b.byteLength) { | ||
| throw new Error('Buffers should be equal in size') | ||
| async function store(id, secretKey, publicKey, pwd) { | ||
| let payload = null | ||
| let kdfOutput = null | ||
| const checkSum = Buffer.alloc(sodium.crypto_generichash_BYTES) | ||
| const salt = Buffer.alloc(32) | ||
| const params = { | ||
| ops: sodium.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE, | ||
| mem: sodium.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE | ||
| } | ||
| for (let i = 0; i < a.length; i++) { | ||
| a[i] ^= b[i] | ||
| try { | ||
| kdfOutput = sodium.sodium_malloc(id.byteLength + secretKey.byteLength + checkSum.byteLength) | ||
| sodium.randombytes_buf(salt) | ||
| const checkSumData = c.encode(LabelledKey, { id, secretKey }) | ||
| sodium.crypto_generichash(checkSum, checkSumData) | ||
| free(checkSumData) | ||
| payload = c.encode(KeyDescriptor, { | ||
| id, | ||
| secretKey, | ||
| checkSum | ||
| }) | ||
| free(secretKey) | ||
| sodium.sodium_mprotect_readwrite(pwd) | ||
| await sodium.crypto_pwhash_scryptsalsa208sha256_async( | ||
| kdfOutput, | ||
| pwd, | ||
| salt, | ||
| params.ops, | ||
| params.mem | ||
| ) | ||
| } finally { | ||
| free(pwd) | ||
| } | ||
| try { | ||
| xor(payload, kdfOutput) | ||
| } finally { | ||
| free(kdfOutput) | ||
| } | ||
| const encrypted = c.encode(EncryptedKey, { | ||
| version: MAX_KEY_VERSION, | ||
| params, | ||
| salt, | ||
| payload, | ||
| publicKey | ||
| }) | ||
| free(payload) | ||
| return { | ||
| id, | ||
| publicKey, | ||
| secretKey: encrypted | ||
| } | ||
| } | ||
| function getKeyInfo(keyBuffer) { | ||
| try { | ||
| const info = c.decode(EncryptedKey, keyBuffer) | ||
| return info | ||
| } catch (err) { | ||
| throw new Error('Invalid key') | ||
| } | ||
| } | ||
| function free(buffer) { | ||
| try { | ||
| sodium.sodium_mprotect_readwrite(buffer) | ||
| } catch { | ||
| // ignore, not a sodium buffer | ||
| } | ||
| sodium.sodium_memzero(buffer) | ||
| sodium.sodium_free(buffer) | ||
| } | ||
| module.exports = { | ||
@@ -219,4 +295,16 @@ generateKeys, | ||
| free, | ||
| getKeyInfo, | ||
| migrate, | ||
| isRequest: request.isRequest, | ||
| isResponse: request.isResponse | ||
| } | ||
| function xor(a, b) { | ||
| if (a.byteLength !== b.byteLength) { | ||
| throw new Error('Buffers should be equal in size') | ||
| } | ||
| for (let i = 0; i < a.length; i++) { | ||
| a[i] ^= b[i] | ||
| } | ||
| } |
+1
-1
| { | ||
| "name": "hypercore-sign-lib", | ||
| "version": "1.0.0", | ||
| "version": "1.1.0", | ||
| "description": "Sign Hypercores", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/holepunchto/hypercore-sign-lib#readme", |
22856
8.72%329
26.54%