Revert "Replace bcrypto with standalone libraries"

This commit is contained in:
Belma Gutlic
2020-04-22 19:03:41 +02:00
committed by GitHub
parent 4506936456
commit 7b11f5a3ab
11 changed files with 124 additions and 738 deletions

View File

@ -1,8 +1,9 @@
import {Buffer} from 'buffer';
import BN from 'bn.js';
import { Buffer } from 'buffer';
export type bytes = Buffer;
export type bytes32 = Buffer;
export type bytes16 = Buffer;
export type uint32 = number;
export type uint64 = number;
export type uint64 = BN;

View File

@ -1,7 +1,5 @@
import {Buffer} from "buffer";
import hash from 'hash.js';
import {box} from 'tweetnacl';
import {AEAD} from 'aead-js';
import { AEAD, x25519, SHA256 } from 'bcrypto';
import {bytes, bytes32, uint32} from "../@types/basic";
import {CipherState, MessageBuffer, SymmetricState} from "../@types/handshake";
@ -106,8 +104,10 @@ export abstract class AbstractHandshake {
protected dh(privateKey: bytes32, publicKey: bytes32): bytes32 {
try {
const sharedKey = box.before(publicKey, privateKey)
return Buffer.from(sharedKey.buffer, sharedKey.byteOffset, sharedKey.length);
const derived = x25519.derive(publicKey, privateKey);
const result = Buffer.alloc(32);
derived.copy(result);
return result;
} catch (e) {
logger(e.message);
return Buffer.alloc(32);
@ -119,8 +119,7 @@ export abstract class AbstractHandshake {
}
protected getHash(a: bytes, b: bytes): bytes32 {
const hashValue = hash.sha256().update(Buffer.from([...a, ...b])).digest();
return Buffer.from(hashValue);
return SHA256.digest(Buffer.from([...a, ...b]));
}
protected mixKey(ss: SymmetricState, ikm: bytes32): void {

View File

@ -1,4 +1,6 @@
import {Buffer} from "buffer";
import BN from "bn.js";
import {CipherState, HandshakeState, MessageBuffer, NoiseSession} from "../@types/handshake";
import {bytes, bytes32} from "../@types/basic";
import {generateKeypair, isValidPublicKey} from "../utils";
@ -20,21 +22,21 @@ export class IK extends AbstractHandshake {
return {
hs,
i: initiator,
mc: 0,
mc: new BN(0),
};
}
public sendMessage(session: NoiseSession, message: bytes): MessageBuffer {
let messageBuffer: MessageBuffer;
if (session.mc === 0) {
if (session.mc.eqn(0)) {
messageBuffer = this.writeMessageA(session.hs, message);
} else if (session.mc === 1) {
} else if (session.mc.eqn(1)) {
const { messageBuffer: mb, h, cs1, cs2 } = this.writeMessageB(session.hs, message);
messageBuffer = mb;
session.h = h;
session.cs1 = cs1;
session.cs2 = cs2;
} else if (session.mc > 1) {
} else if (session.mc.gtn(1)) {
if (session.i) {
if (!session.cs1) {
throw new Error("CS1 (cipher state) is not defined")
@ -52,16 +54,16 @@ export class IK extends AbstractHandshake {
throw new Error("Session invalid.")
}
session.mc++;
session.mc = session.mc.add(new BN(1));
return messageBuffer;
}
public recvMessage(session: NoiseSession, message: MessageBuffer): {plaintext: bytes; valid: boolean} {
let plaintext = Buffer.alloc(0), valid = false;
if (session.mc === 0) {
if (session.mc.eqn(0)) {
({plaintext, valid} = this.readMessageA(session.hs, message));
}
if (session.mc === 1) {
if (session.mc.eqn(1)) {
const { plaintext: pt, valid: v, h, cs1, cs2 } = this.readMessageB(session.hs, message);
plaintext = pt;
valid = v;
@ -69,7 +71,7 @@ export class IK extends AbstractHandshake {
session.cs1 = cs1;
session.cs2 = cs2;
}
session.mc++;
session.mc = session.mc.add(new BN(1));
return {plaintext, valid};
}

View File

@ -1,4 +1,6 @@
import { Buffer } from 'buffer';
import BN from 'bn.js';
import { bytes32, bytes } from '../@types/basic'
import { KeyPair } from '../@types/libp2p'
import {generateKeypair, isValidPublicKey} from '../utils';
@ -127,23 +129,23 @@ export class XX extends AbstractHandshake {
return {
hs,
i: initiator,
mc: 0,
mc: new BN(0),
};
}
public sendMessage(session: NoiseSession, message: bytes, ephemeral?: KeyPair): MessageBuffer {
let messageBuffer: MessageBuffer;
if (session.mc === 0) {
if (session.mc.eqn(0)) {
messageBuffer = this.writeMessageA(session.hs, message, ephemeral);
} else if (session.mc === 1) {
} else if (session.mc.eqn(1)) {
messageBuffer = this.writeMessageB(session.hs, message);
} else if (session.mc === 2) {
} else if (session.mc.eqn(2)) {
const { h, messageBuffer: resultingBuffer, cs1, cs2 } = this.writeMessageC(session.hs, message);
messageBuffer = resultingBuffer;
session.h = h;
session.cs1 = cs1;
session.cs2 = cs2;
} else if (session.mc > 2) {
} else if (session.mc.gtn(2)) {
if (session.i) {
if (!session.cs1) {
throw new Error("CS1 (cipher state) is not defined")
@ -161,18 +163,18 @@ export class XX extends AbstractHandshake {
throw new Error("Session invalid.")
}
session.mc++;
session.mc = session.mc.add(new BN(1));
return messageBuffer;
}
public recvMessage(session: NoiseSession, message: MessageBuffer): {plaintext: bytes; valid: boolean} {
let plaintext: bytes = Buffer.alloc(0);
let valid = false;
if (session.mc === 0) {
if (session.mc.eqn(0)) {
({plaintext, valid} = this.readMessageA(session.hs, message));
} else if (session.mc === 1) {
} else if (session.mc.eqn(1)) {
({plaintext, valid} = this.readMessageB(session.hs, message));
} else if (session.mc === 2) {
} else if (session.mc.eqn(2)) {
const { h, plaintext: resultingPlaintext, valid: resultingValid, cs1, cs2 } = this.readMessageC(session.hs, message);
plaintext = resultingPlaintext;
valid = resultingValid;
@ -180,7 +182,7 @@ export class XX extends AbstractHandshake {
session.cs1 = cs1;
session.cs2 = cs2;
}
session.mc++;
session.mc = session.mc.add(new BN(1));
return {plaintext, valid};
}
}

View File

@ -1,4 +1,4 @@
import {box} from 'tweetnacl';
import {x25519} from 'bcrypto';
import {Buffer} from "buffer";
import Wrap from 'it-pb-rpc';
import DuplexPair from 'it-pair/duplex';
@ -49,7 +49,7 @@ export class Noise implements INoiseConnection {
this.useNoisePipes = false;
if (staticNoiseKey) {
const publicKey = Buffer.from(box.keyPair.fromSecretKey(staticNoiseKey).publicKey);
const publicKey = x25519.publicKeyCreate(staticNoiseKey);
this.staticKeys = {
privateKey: staticNoiseKey,
publicKey,

View File

@ -1,8 +1,7 @@
import hkdf from 'futoin-hkdf';
import {box} from 'tweetnacl';
import {HKDF, SHA256, x25519} from 'bcrypto';
import {Buffer} from "buffer";
import PeerId from "peer-id";
import {keys} from 'libp2p-crypto';
import * as crypto from 'libp2p-crypto';
import {KeyPair} from "./@types/libp2p";
import {bytes, bytes32} from "./@types/basic";
import {Hkdf, INoisePayload} from "./@types/handshake";
@ -11,9 +10,8 @@ import {pb} from "./proto/payload";
const NoiseHandshakePayloadProto = pb.NoiseHandshakePayload;
export function generateKeypair(): KeyPair {
const keyPair = box.keyPair();
const publicKey = Buffer.from(keyPair.publicKey);
const privateKey = Buffer.from(keyPair.secretKey);
const privateKey = x25519.privateKeyGenerate();
const publicKey = x25519.publicKeyCreate(privateKey);
return {
publicKey,
@ -93,15 +91,17 @@ export async function verifySignedPayload(
}
const generatedPayload = getHandshakePayload(noiseStaticKey);
// Unmarshaling from PublicKey protobuf
const publicKey = keys.unmarshalPublicKey(identityKey);
if (!publicKey.verify(generatedPayload, payload.identitySig as Buffer)) {
const publicKey = crypto.keys.unmarshalPublicKey(identityKey);
if (!publicKey.verify(generatedPayload, payload.identitySig)) {
throw new Error("Static key doesn't match to peer that signed payload!");
}
return remotePeer;
}
export function getHkdf(ck: bytes32, ikm: bytes): Hkdf {
const okm = hkdf(ikm, 96, {salt: ck, hash: 'SHA-256'});
const info = Buffer.alloc(0);
const prk = HKDF.extract(SHA256, ikm, ck);
const okm = HKDF.expand(SHA256, prk, info, 96);
const k1 = okm.slice(0, 32);
const k2 = okm.slice(32, 64);
@ -111,9 +111,5 @@ export function getHkdf(ck: bytes32, ikm: bytes): Hkdf {
}
export function isValidPublicKey(pk: bytes): boolean {
if(pk.length !== 32 || pk.equals(Buffer.alloc(32))){
return false;
}
return true;
return x25519.publicKeyVerify(pk.slice(0, 32));
}