import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys';
import { UnexpectedPeerError } from '@libp2p/interface';
import { concat as uint8ArrayConcat } from 'uint8arrays/concat';
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
import { NoiseHandshakePayload } from './proto/payload.js';
export async function createHandshakePayload(privateKey, staticPublicKey, extensions) {
    const identitySig = await privateKey.sign(getSignaturePayload(staticPublicKey));
    return NoiseHandshakePayload.encode({
        identityKey: publicKeyToProtobuf(privateKey.publicKey),
        identitySig,
        extensions
    });
}
export async function decodeHandshakePayload(payloadBytes, remoteStaticKey, remoteIdentityKey) {
    try {
        const payload = NoiseHandshakePayload.decode(payloadBytes);
        const publicKey = publicKeyFromProtobuf(payload.identityKey);
        if (remoteIdentityKey?.equals(publicKey) === false) {
            throw new Error(`Payload identity key ${publicKey} does not match expected remote identity key ${remoteIdentityKey}`);
        }
        if (!remoteStaticKey) {
            throw new Error('Remote static does not exist');
        }
        const signaturePayload = getSignaturePayload(remoteStaticKey);
        if (!(await publicKey.verify(signaturePayload, payload.identitySig))) {
            throw new Error('Invalid payload signature');
        }
        return payload;
    }
    catch (e) {
        throw new UnexpectedPeerError(e.message);
    }
}
export function getSignaturePayload(publicKey) {
    const prefix = uint8ArrayFromString('noise-libp2p-static-key:');
    if (publicKey instanceof Uint8Array) {
        return uint8ArrayConcat([prefix, publicKey], prefix.length + publicKey.length);
    }
    publicKey.prepend(prefix);
    return publicKey;
}
//# sourceMappingURL=utils.js.map