js-libp2p-noise/src/utils.ts

96 lines
2.7 KiB
TypeScript
Raw Normal View History

2019-11-20 21:38:14 +01:00
import { x25519, ed25519 } from 'bcrypto';
import protobuf from "protobufjs";
2019-11-22 12:52:59 +01:00
import { Buffer } from "buffer";
2019-11-27 08:39:06 +01:00
import debug from "debug";
2019-11-11 21:58:04 +01:00
2019-11-20 13:23:36 +01:00
import { KeyPair } from "./@types/libp2p";
import { bytes } from "./@types/basic";
2019-11-22 12:52:59 +01:00
import { MessageBuffer } from "./xx";
2019-11-20 21:38:14 +01:00
2019-11-27 08:39:06 +01:00
export const logger = debug('libp2p:noise');
2019-11-20 21:38:14 +01:00
export async function loadPayloadProto () {
const payloadProtoBuf = await protobuf.load("protos/payload.proto");
return payloadProtoBuf.lookupType("pb.NoiseHandshakePayload");
}
2019-11-11 21:58:04 +01:00
2019-11-21 14:43:12 +01:00
export function generateKeypair() : KeyPair {
2019-11-11 21:58:04 +01:00
const privateKey = x25519.privateKeyGenerate();
const publicKey = x25519.publicKeyCreate(privateKey);
return {
publicKey,
privateKey,
}
}
2019-11-20 21:38:14 +01:00
export async function createHandshakePayload(
2019-11-21 13:38:39 +01:00
libp2pPublicKey: bytes,
2019-11-28 17:32:46 +01:00
libp2pPrivateKey: bytes,
2019-11-20 21:38:14 +01:00
signedPayload: bytes,
2019-11-28 17:32:46 +01:00
signedEarlyData?: EarlyDataPayload,
2019-11-20 21:38:14 +01:00
) : Promise<bytes> {
const NoiseHandshakePayload = await loadPayloadProto();
2019-11-28 17:32:46 +01:00
const earlyDataPayload = signedEarlyData ?
{
libp2pData: signedEarlyData.libp2pData,
libp2pDataSignature: signedEarlyData.libp2pDataSignature,
} : {};
2019-11-20 21:38:14 +01:00
const payloadInit = NoiseHandshakePayload.create({
2019-11-21 13:38:39 +01:00
libp2pKey: libp2pPublicKey,
2019-11-20 21:38:14 +01:00
noiseStaticKeySignature: signedPayload,
2019-11-28 17:32:46 +01:00
...earlyDataPayload,
2019-11-20 21:38:14 +01:00
});
return Buffer.from(NoiseHandshakePayload.encode(payloadInit).finish());
}
2019-11-28 17:32:46 +01:00
export function signPayload(libp2pPrivateKey: bytes, payload: bytes) {
return ed25519.sign(payload, libp2pPrivateKey);
2019-11-11 21:58:04 +01:00
}
2019-11-20 21:38:14 +01:00
2019-11-28 17:32:46 +01:00
type EarlyDataPayload = {
libp2pData: bytes;
libp2pDataSignature: bytes;
}
2019-11-20 21:38:14 +01:00
2019-11-28 17:32:46 +01:00
export function signEarlyDataPayload(libp2pPrivateKey: bytes, earlyData: bytes) : EarlyDataPayload {
2019-11-20 21:38:14 +01:00
const payload = getEarlyDataPayload(earlyData);
2019-11-28 17:32:46 +01:00
const signedPayload = signPayload(libp2pPrivateKey, payload);
2019-11-20 21:38:14 +01:00
return {
libp2pData: payload,
libp2pDataSignature: signedPayload,
}
}
2019-11-28 17:32:46 +01:00
export const getHandshakePayload = (publicKey: bytes ) => Buffer.concat([Buffer.from("noise-libp2p-static-key:"), publicKey]);
export const getEarlyDataPayload = (earlyData: bytes) => Buffer.concat([Buffer.from("noise-libp2p-early-data:"), earlyData]);
2019-11-22 12:52:59 +01:00
export function encodeMessageBuffer(message: MessageBuffer) : bytes {
return Buffer.concat([message.ne, message.ns, message.ciphertext]);
}
export function decodeMessageBuffer(message: bytes) : MessageBuffer {
return {
ne: message.slice(0, 32),
2019-11-28 17:32:46 +01:00
ns: message.slice(32, 64),
ciphertext: message.slice(64, message.length),
2019-11-22 12:52:59 +01:00
}
}
2019-11-27 14:19:35 +01:00
export const int16BEEncode = (value, target, offset) => {
target = target || Buffer.allocUnsafe(2);
return target.writeInt16BE(value, offset);
};
int16BEEncode.bytes = 2;
export const int16BEDecode = data => {
if (data.length < 2) throw RangeError('Could not decode int16BE');
2019-11-28 17:32:46 +01:00
return data.readInt16BE(0);
};
2019-11-27 14:19:35 +01:00
int16BEDecode.bytes = 2;