/// <summary> /// Signs a set of messages featuring both known and blinded messages to the signer and produces a BBS+ signature /// </summary> /// <param name="keyPair">The signing key containing the secret BLS key.</param> /// <param name="commitment">The commitment.</param> /// <param name="messages">The messages.</param> /// <returns></returns> public static byte[] BlindSign(BlindSignRequest request) { using var context = new UnmanagedMemoryContext(); var handle = Native.bbs_blind_sign_context_init(out var error); context.ThrowIfNeeded(error); foreach (var item in request.Messages) { Native.bbs_blind_sign_context_add_message_string(handle, item.Index, item.Message, out error); context.ThrowIfNeeded(error); } Native.bbs_blind_sign_context_set_public_key(handle, context.ToBuffer(request.PublicKey), out error); context.ThrowIfNeeded(error); Native.bbs_blind_sign_context_set_secret_key(handle, context.ToBuffer(request.SecretKey.SecretKey.ToArray()), out error); context.ThrowIfNeeded(error); Native.bbs_blind_sign_context_set_commitment(handle, context.ToBuffer(request.Commitment), out error); context.ThrowIfNeeded(error); Native.bbs_blind_sign_context_finish(handle, out var blindedSignature, out error); context.ThrowIfNeeded(error); return context.ToByteArray(blindedSignature); }
/// <summary> /// Signs a set of messages with a BBS key pair and produces a BBS signature /// </summary> /// <param name="signRequest">Request for the sign operation</param> /// <returns>The raw signature value</returns> /// <exception cref="BbsException"> /// Secret key not found /// or /// Messages cannot be null /// </exception> public static byte[] Sign(SignRequest signRequest) { if (signRequest?.KeyPair?.SecretKey is null) throw new BbsException("Secret key not found"); if (signRequest?.Messages is null) throw new BbsException("Messages cannot be null"); var bbsKeyPair = signRequest.KeyPair.GeyBbsKeyPair((uint)signRequest.Messages.Length); using var context = new UnmanagedMemoryContext(); var handle = Native.bbs_sign_context_init(out var error); context.ThrowIfNeeded(error); foreach (var message in signRequest.Messages) { Native.bbs_sign_context_add_message_string(handle, message, out error); context.ThrowIfNeeded(error); } Native.bbs_sign_context_set_public_key(handle, context.ToBuffer(bbsKeyPair.PublicKey), out error); context.ThrowIfNeeded(error); Native.bbs_sign_context_set_secret_key(handle, context.ToBuffer(signRequest.KeyPair.SecretKey!), out error); context.ThrowIfNeeded(error); Native.bbs_sign_context_finish(handle, out var signature, out error); context.ThrowIfNeeded(error); return context.ToByteArray(signature); }
/// <summary> /// Verifies a blinded commitment of messages /// </summary> /// <param name="request">Request for the commitment verification</param> /// <returns></returns> public static SignatureProofStatus VerifyBlindedCommitment(VerifyBlindedCommitmentRequest request) { using var context = new UnmanagedMemoryContext(); var handle = Native.bbs_verify_blind_commitment_context_init(out var error); context.ThrowIfNeeded(error); Native.bbs_verify_blind_commitment_context_set_nonce_string(handle, request.Nonce, out error); context.ThrowIfNeeded(error); Native.bbs_verify_blind_commitment_context_set_proof(handle, context.ToBuffer(request.Proof), out error); context.ThrowIfNeeded(error); Native.bbs_verify_blind_commitment_context_set_public_key(handle, context.ToBuffer(request.PublicKey), out error); context.ThrowIfNeeded(error); foreach (var index in request.BlindedIndices) { Native.bbs_verify_blind_commitment_context_add_blinded(handle, index, out error); context.ThrowIfNeeded(error); } var result = Native.bbs_verify_blind_commitment_context_finish(handle, out error); context.ThrowIfNeeded(error); return Task.FromResult((SignatureProofStatus)result); }
/// <summary> /// Unblinds the signature asynchronous. /// </summary> /// <param name="request">Unbling signature request</param> /// <returns></returns> public static byte[] UnblindSignature(UnblindSignatureRequest request) { using var context = new UnmanagedMemoryContext(); Native.bbs_unblind_signature(context.ToBuffer(request.BlindedSignature), context.ToBuffer(request.BlindingFactor), out var unblindedSignature, out var error); context.ThrowIfNeeded(error); return(context.ToByteArray(unblindedSignature)); }
/// <summary> /// Generates new BBS+ public key from the current BLS12-381 /// </summary> /// <param name="messageCount">The message count.</param> /// <returns></returns> public BbsKeyPair GeyBbsKeyPair(uint messageCount) { using var context = new UnmanagedMemoryContext(); if (SecretKey is null) { Native.bls_public_key_to_bbs_key(context.ToBuffer(PublicKey), messageCount, out var publicKey, out var error); context.ThrowIfNeeded(error); return(new BbsKeyPair(context.ToByteArray(publicKey), messageCount)); } else { Native.bls_secret_key_to_bbs_key(context.ToBuffer(SecretKey), messageCount, out var publicKey, out var error); context.ThrowIfNeeded(error); return(new BbsKeyPair(context.ToByteArray(publicKey), messageCount)); } }
public BbsPublicKey GeneratePublicKey(uint messageCount) { unsafe { using var context = new UnmanagedMemoryContext(); context.Reference(Key.ToArray(), out var dPublicKey); NativeMethods.bls_public_key_to_bbs_key(&dPublicKey, messageCount, out var publicKey, out var error); error.ThrowIfNeeded(); context.Dereference(publicKey, out var pk); return(new BbsPublicKey { Key = new ReadOnlyCollection <byte>(pk), MessageCount = messageCount }); } }
/// <summary> /// Creates new <see cref="BlsSecretKey"/> using a input seed as byte array. /// </summary> /// <param name="seed">The seed.</param> /// <returns></returns> public static BlsSecretKey Generate(byte[] seed) { using var context = new UnmanagedMemoryContext(); unsafe { context.Reference(seed, out var seed_); var result = NativeMethods.bls_generate_key(&seed_, out var pk, out var sk, out var error); context.Dereference(pk, out var publicKey); context.Dereference(sk, out var secretKey); return(result switch { 0 => new BlsSecretKey { Key = new ReadOnlyCollection <byte>(secretKey) }, _ => throw error.Dereference() });
public BlsKeyPair(byte[] keyData) { if (keyData.Length == SecretKeySize) { SecretKey = new ReadOnlyCollection <byte>(keyData); using var context = new UnmanagedMemoryContext(); Native.bls_get_public_key(context.ToBuffer(keyData), out var publicKey, out var error); context.ThrowIfNeeded(error); PublicKey = context.ToReadOnlyCollection(publicKey); } else if (keyData.Length == PublicKeySize) { PublicKey = new ReadOnlyCollection <byte>(keyData); } else { throw new BbsException("Invalid key size"); } }
/// <summary> /// Gets the deterministic public key. /// </summary> /// <returns></returns> public BlsDeterministicPublicKey GetDeterministicPublicKey() { using var context = new UnmanagedMemoryContext(); if (_dPublicKey != null) { return(_dPublicKey); } context.Reference(Key.ToArray(), out var secretKey); unsafe { NativeMethods.bls_get_public_key(&secretKey, out var publicKey, out var error); error.ThrowIfNeeded(); context.Dereference(publicKey, out var pk); return(_dPublicKey = new BlsDeterministicPublicKey { Key = new ReadOnlyCollection <byte>(pk) }); } }
/// <summary> /// Verifies a BBS+ signature for a set of messages with a BBS public key /// </summary> /// <param name="verifyRequest">Request for the signature verification operation</param> /// <returns> /// A result indicating if the signature was verified /// </returns> public static bool Verify(VerifyRequest verifyRequest) { using var context = new UnmanagedMemoryContext(); var handle = Native.bbs_verify_context_init(out var error); context.ThrowIfNeeded(error); Native.bbs_verify_context_set_public_key(handle, context.ToBuffer(verifyRequest.KeyPair.PublicKey), out error); context.ThrowIfNeeded(error); Native.bbs_verify_context_set_signature(handle, context.ToBuffer(verifyRequest.Signature), out error); context.ThrowIfNeeded(error); foreach (var message in verifyRequest.Messages) { Native.bbs_verify_context_add_message_string(handle, message, out error); context.ThrowIfNeeded(error); } var result = Native.bbs_verify_context_finish(handle, out error); context.ThrowIfNeeded(error); return result == 1; }
/// <summary> /// Create a blinded commitment of messages for use in producing a blinded BBS+ signature /// </summary> /// <param name="request">Request for producing the blinded commitment</param> /// <returns></returns> public static BlindedCommitment CreateBlindedCommitment(CreateBlindedCommitmentRequest request) { using var context = new UnmanagedMemoryContext(); var handle = Native.bbs_blind_commitment_context_init(out var error); context.ThrowIfNeeded(error); foreach (var item in request.Messages) { Native.bbs_blind_commitment_context_add_message_string(handle, item.Index, item.Message, out error); context.ThrowIfNeeded(error); } Native.bbs_blind_commitment_context_set_nonce_string(handle, request.Nonce, out error); context.ThrowIfNeeded(error); Native.bbs_blind_commitment_context_set_public_key(handle, context.ToBuffer(request.PublicKey), out error); context.ThrowIfNeeded(error); Native.bbs_blind_commitment_context_finish(handle, out var commitment, out var outContext, out var blindingFactor, out error); context.ThrowIfNeeded(error); return new BlindedCommitment(context.ToByteArray(outContext), context.ToByteArray(blindingFactor), context.ToByteArray(commitment)); }
/// <summary> /// Create a <see cref="ByteBuffer"/> from a <see cref="BbsKeyPair"/> /// </summary> /// <param name="buffer"></param> /// <returns></returns> internal static ByteBuffer ToBuffer(this UnmanagedMemoryContext context, BbsKeyPair keyPair) => context.ToBuffer(keyPair.PublicKey.ToArray());
/// <summary> /// Create a <see cref="ByteBuffer"/> from a <see cref="ReadOnlyCollection{byte}"/> /// </summary> /// <param name="buffer"></param> /// <returns></returns> internal static ByteBuffer ToBuffer(this UnmanagedMemoryContext context, ReadOnlyCollection <byte> buffer) => context.ToBuffer(buffer.ToArray());