UNPKG

libp2p-pubsub

Version:
84 lines 3.14 kB
import * as PeerIdFactory from 'libp2p-peer-id-factory'; import { RPC } from './rpc.js'; import { concat as uint8ArrayConcat } from 'uint8arrays/concat'; import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'; import { normalizeOutRpcMessage } from '../utils.js'; import { PeerId } from 'libp2p-peer-id'; import { keys } from 'libp2p-crypto'; export const SignPrefix = uint8ArrayFromString('libp2p-pubsub:'); /** * Signs the provided message with the given `peerId` */ export async function signMessage(peerId, message) { // Get the message in bytes, and prepend with the pubsub prefix const bytes = uint8ArrayConcat([ SignPrefix, RPC.Message.encode(normalizeOutRpcMessage(message)).finish() ]); if (peerId.privateKey == null) { throw new Error('Cannot sign message, no private key present'); } if (peerId.publicKey == null) { throw new Error('Cannot sign message, no public key present'); } const privateKey = await keys.unmarshalPrivateKey(peerId.privateKey); const signature = await privateKey.sign(bytes); const outputMessage = { ...message, signature: signature, key: peerId.publicKey }; return outputMessage; } /** * Verifies the signature of the given message */ export async function verifySignature(message) { if (message.signature == null) { throw new Error('Message must contain a signature to be verified'); } if (message.from == null) { throw new Error('Message must contain a from property to be verified'); } // Get message sans the signature const bytes = uint8ArrayConcat([ SignPrefix, RPC.Message.encode({ ...message, signature: undefined, key: undefined }).finish() ]); // Get the public key const pubKeyBytes = await messagePublicKey(message); const pubKey = keys.unmarshalPublicKey(pubKeyBytes); // verify the base message return await pubKey.verify(bytes, message.signature); } /** * Returns the PublicKey associated with the given message. * If no, valid PublicKey can be retrieved an error will be returned. */ export async function messagePublicKey(message) { // should be available in the from property of the message (peer id) if (message.from == null) { throw new Error('Could not get the public key from the originator id'); } const from = PeerId.fromBytes(message.from); if (message.key != null) { const keyPeerId = await PeerIdFactory.createFromPubKey(keys.unmarshalPublicKey(message.key)); // the key belongs to the sender, return the key if (!keyPeerId.equals(from)) { throw new Error('Public Key does not match the originator'); } if (keyPeerId.publicKey != null) { return keyPeerId.publicKey; } } else if (from.publicKey != null) { return from.publicKey; } // We couldn't validate pubkey is from the originator, error throw new Error('Could not get the public key from the originator id'); } //# sourceMappingURL=sign.js.map