Skip to content

Remove bcypto #100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jun 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
needs: check
strategy:
matrix:
node: [14]
node: [14, 15]
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
runs-on: ${{ matrix.os }}
steps:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
coverage/*
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
"sinon": "^10.0.0"
},
"dependencies": {
"bcrypto": "^5.4.0",
"@stablelib/chacha20poly1305": "^1.0.1",
"@stablelib/hkdf": "^1.0.1",
"@stablelib/sha256": "^1.0.1",
"@stablelib/x25519": "^1.0.1",
"debug": "^4.3.1",
"it-buffer": "^0.1.1",
"it-length-prefixed": "^5.0.2",
Expand Down
53 changes: 31 additions & 22 deletions src/handshakes/abstract-handshake.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Buffer } from 'buffer'
import AEAD from 'bcrypto/lib/js/aead'
import x25519 from 'bcrypto/lib/js/x25519'
import SHA256 from 'bcrypto/lib/js/sha256'
import * as x25519 from '@stablelib/x25519'
import * as SHA256 from '@stablelib/sha256'
import { ChaCha20Poly1305 } from '@stablelib/chacha20poly1305'

import { bytes, bytes32, uint32 } from '../@types/basic'
import { CipherState, MessageBuffer, SymmetricState } from '../@types/handshake'
Expand Down Expand Up @@ -56,14 +56,9 @@ export abstract class AbstractHandshake {

protected encrypt (k: bytes32, n: uint32, ad: bytes, plaintext: bytes): bytes {
const nonce = this.nonceToBytes(n)
const ctx = new AEAD()
plaintext = Buffer.from(plaintext)
ctx.init(k, nonce)
ctx.aad(ad)
ctx.encrypt(plaintext)

// Encryption is done on the sent reference
return Buffer.concat([plaintext, ctx.final()])
const ctx = new ChaCha20Poly1305(k)
const encryptedMessage = ctx.seal(nonce, plaintext, ad)
return Buffer.from(encryptedMessage.buffer, encryptedMessage.byteOffset, encryptedMessage.length)
}

protected encryptAndHash (ss: SymmetricState, plaintext: bytes): bytes {
Expand All @@ -80,15 +75,27 @@ export abstract class AbstractHandshake {

protected decrypt (k: bytes32, n: uint32, ad: bytes, ciphertext: bytes): {plaintext: bytes, valid: boolean} {
const nonce = this.nonceToBytes(n)
const ctx = new AEAD()
ciphertext = Buffer.from(ciphertext)
const tag = ciphertext.slice(ciphertext.length - 16)
ciphertext = ciphertext.slice(0, ciphertext.length - 16)
ctx.init(k, nonce)
ctx.aad(ad)
ctx.decrypt(ciphertext)
// Decryption is done on the sent reference
return { plaintext: ciphertext, valid: ctx.verify(tag) }
const ctx = new ChaCha20Poly1305(k)
const encryptedMessage = ctx.open(
nonce,
ciphertext,
ad
)
if (encryptedMessage) {
return {
plaintext: Buffer.from(
encryptedMessage.buffer,
encryptedMessage.byteOffset,
encryptedMessage.length
),
valid: true
}
} else {
return {
plaintext: Buffer.from(''),
valid: false
}
}
}

protected decryptAndHash (ss: SymmetricState, ciphertext: bytes): {plaintext: bytes, valid: boolean} {
Expand All @@ -105,7 +112,8 @@ export abstract class AbstractHandshake {

protected dh (privateKey: bytes32, publicKey: bytes32): bytes32 {
try {
const derived = x25519.derive(publicKey, privateKey)
const derivedU8 = x25519.sharedKey(privateKey, publicKey)
const derived = Buffer.from(derivedU8.buffer, derivedU8.byteOffset, derivedU8.length)
const result = Buffer.alloc(32)
derived.copy(result)
return result
Expand All @@ -120,7 +128,8 @@ export abstract class AbstractHandshake {
}

protected getHash (a: bytes, b: bytes): bytes32 {
return SHA256.digest(Buffer.from([...a, ...b]))
const hash = SHA256.hash(Buffer.from([...a, ...b]))
return Buffer.from(hash.buffer, hash.byteOffset, hash.length)
}

protected mixKey (ss: SymmetricState, ikm: bytes32): void {
Expand Down
17 changes: 13 additions & 4 deletions src/noise.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import x25519 from 'bcrypto/lib/js/x25519'
import * as x25519 from '@stablelib/x25519'
import { Buffer } from 'buffer'
import Wrap from 'it-pb-rpc'
import DuplexPair from 'it-pair/duplex'
Expand Down Expand Up @@ -49,10 +49,19 @@ export class Noise implements INoiseConnection {
this.useNoisePipes = false

if (staticNoiseKey) {
const publicKey = x25519.publicKeyCreate(staticNoiseKey)
// accepts x25519 private key of length 32
const keyPair = x25519.generateKeyPairFromSeed(staticNoiseKey)
this.staticKeys = {
privateKey: staticNoiseKey,
publicKey
privateKey: Buffer.from(
keyPair.secretKey.buffer,
keyPair.secretKey.byteOffset,
keyPair.secretKey.length
),
publicKey: Buffer.from(
keyPair.publicKey.buffer,
keyPair.publicKey.byteOffset,
keyPair.publicKey.length
)
}
} else {
this.staticKeys = generateKeypair()
Expand Down
31 changes: 19 additions & 12 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import HKDF from 'bcrypto/lib/hkdf'
import x25519 from 'bcrypto/lib/js/x25519'
import SHA256 from 'bcrypto/lib/js/sha256'
import { HKDF } from '@stablelib/hkdf'
import { SHA256 } from '@stablelib/sha256'
import * as x25519 from '@stablelib/x25519'
import { Buffer } from 'buffer'
import PeerId from 'peer-id'
import { keys } from 'libp2p-crypto'
Expand All @@ -13,12 +13,11 @@ import uint8ArrayEquals from 'uint8arrays/equals'
const NoiseHandshakePayloadProto = pb.NoiseHandshakePayload

export function generateKeypair (): KeyPair {
const privateKey = x25519.privateKeyGenerate()
const publicKey = x25519.publicKeyCreate(privateKey)
const keypair = x25519.generateKeyPair()

return {
publicKey,
privateKey
publicKey: Buffer.from(keypair.publicKey.buffer, keypair.publicKey.byteOffset, keypair.publicKey.length),
privateKey: Buffer.from(keypair.secretKey.buffer, keypair.secretKey.byteOffset, keypair.secretKey.length)
}
}

Expand Down Expand Up @@ -69,7 +68,7 @@ export function getHandshakePayload (publicKey: bytes): bytes {
return Buffer.concat([Buffer.from('noise-libp2p-static-key:'), publicKey])
}

async function isValidPeerId (peerId: Uint8Array, publicKeyProtobuf: bytes) {
async function isValidPeerId (peerId: Uint8Array, publicKeyProtobuf: bytes): Promise<boolean> {
const generatedPeerId = await PeerId.createFromPubKey(publicKeyProtobuf)
return uint8ArrayEquals(generatedPeerId.id, peerId)
}
Expand Down Expand Up @@ -103,9 +102,9 @@ export async function verifySignedPayload (
}

export function getHkdf (ck: bytes32, ikm: bytes): Hkdf {
const info = Buffer.alloc(0)
const prk = HKDF.extract(SHA256, ikm, ck)
const okm = HKDF.expand(SHA256, prk, info, 96)
const hkdf = new HKDF(SHA256, ikm, ck)
const okmU8Array = hkdf.expand(96)
const okm = Buffer.from(okmU8Array.buffer, okmU8Array.byteOffset, okmU8Array.length)

const k1 = okm.slice(0, 32)
const k2 = okm.slice(32, 64)
Expand All @@ -115,5 +114,13 @@ export function getHkdf (ck: bytes32, ikm: bytes): Hkdf {
}

export function isValidPublicKey (pk: bytes): boolean {
return x25519.publicKeyVerify(pk.slice(0, 32))
if (!Buffer.isBuffer(pk)) {
return false
}

if (pk.length !== 32) {
return false
}

return true
}
Loading