private bool FastAggregateVerifyData(IList <byte[]>?publicKeyList, ReadOnlySpan <byte> publicKeysSpan, ReadOnlySpan <byte> data, ReadOnlySpan <byte> aggregateSignature) { // This is independent of the keys set, although other parameters (type of curve, variant, scheme, etc) are relevant. if (aggregateSignature.Length != SignatureLength) { throw new ArgumentOutOfRangeException(nameof(aggregateSignature), aggregateSignature.Length, $"Signature must be {SignatureLength} bytes long."); } EnsureInitialised(); var publicKeyCount = publicKeyList?.Count ?? publicKeysSpan.Length / PublicKeyLength; var blsPublicKeys = new Bls384Interop.BlsPublicKey[publicKeyCount]; if (publicKeyList == null) { if (publicKeysSpan.Length % PublicKeyLength != 0) { throw new ArgumentOutOfRangeException(nameof(publicKeysSpan), publicKeysSpan.Length, $"Public key data must be a multiple of the public key length {PublicKeyLength}."); } } var publicKeysIndex = 0; for (var blsPublicKeyIndex = 0; blsPublicKeyIndex < publicKeyCount; blsPublicKeyIndex++) { var publicKey = (publicKeyList != null) ? publicKeyList[blsPublicKeyIndex] : publicKeysSpan.Slice(publicKeysIndex, PublicKeyLength); int publicKeyBytesRead; unsafe { fixed(byte *publicKeyPtr = publicKey) { publicKeyBytesRead = Bls384Interop.PublicKeyDeserialize( ref blsPublicKeys[blsPublicKeyIndex], publicKeyPtr, PublicKeyLength); } } if (publicKeyBytesRead != PublicKeyLength) { throw new Exception( $"Error deserializing BLS public key {blsPublicKeyIndex}, length: {publicKeyBytesRead}"); } publicKeysIndex += PublicKeyLength; } var aggregateBlsSignature = default(Bls384Interop.BlsSignature); int signatureBytesRead; unsafe { fixed(byte *signaturePtr = aggregateSignature) { signatureBytesRead = Bls384Interop.SignatureDeserialize(ref aggregateBlsSignature, signaturePtr, SignatureLength); } } if (signatureBytesRead != aggregateSignature.Length) { throw new Exception($"Error deserializing BLS signature, length: {signatureBytesRead}"); } int result; unsafe { fixed(byte *dataPtr = data) { result = Bls384Interop.FastAggregateVerify(ref aggregateBlsSignature, blsPublicKeys, publicKeyCount, dataPtr, data.Length); } } return(result == 1); }
/// <inheritdoc /> public override bool AggregateVerifyData(ReadOnlySpan <byte> publicKeys, ReadOnlySpan <byte> data, ReadOnlySpan <byte> aggregateSignature) { // NOTE: all msg[i] has the same msgSize byte, so msgVec must have (msgSize * n) byte area // TODO: CHECK that sig has the valid order, all msg are different each other before calling this // This is independent of the keys set, although other parameters (type of curve, variant, scheme, etc) are relevant. if (aggregateSignature.Length != SignatureLength) { throw new ArgumentOutOfRangeException(nameof(aggregateSignature), aggregateSignature.Length, $"Signature must be {SignatureLength} bytes long."); } if (publicKeys.Length % PublicKeyLength != 0) { throw new ArgumentOutOfRangeException(nameof(publicKeys), publicKeys.Length, $"Public key data must be a multiple of the public key length {PublicKeyLength}."); } var publicKeyCount = publicKeys.Length / PublicKeyLength; if (data.Length % publicKeyCount != 0) { throw new ArgumentOutOfRangeException(nameof(data), data.Length, $"Data must all be the same length, with total bytes evenly divisible by the number of public keys, {publicKeyCount}."); } EnsureInitialised(); var blsPublicKeys = new Bls384Interop.BlsPublicKey[publicKeyCount]; var publicKeysIndex = 0; for (var blsPublicKeyIndex = 0; blsPublicKeyIndex < publicKeyCount; blsPublicKeyIndex++) { var publicKey = publicKeys.Slice(publicKeysIndex, PublicKeyLength); int publicKeyBytesRead; unsafe { fixed(byte *publicKeyPtr = publicKey) { publicKeyBytesRead = Bls384Interop.PublicKeyDeserialize(ref blsPublicKeys[blsPublicKeyIndex], publicKeyPtr, PublicKeyLength); } } if (publicKeyBytesRead != PublicKeyLength) { throw new Exception( $"Error deserializing BLS public key {blsPublicKeyIndex}, length: {publicKeyBytesRead}"); } publicKeysIndex += PublicKeyLength; } var aggregateBlsSignature = default(Bls384Interop.BlsSignature); int signatureBytesRead; unsafe { fixed(byte *signaturePtr = aggregateSignature) { signatureBytesRead = Bls384Interop.SignatureDeserialize(ref aggregateBlsSignature, signaturePtr, SignatureLength); } } if (signatureBytesRead != aggregateSignature.Length) { throw new Exception($"Error deserializing BLS signature, length: {signatureBytesRead}"); } int result; var dataItemLength = data.Length / publicKeyCount; unsafe { fixed(byte *dataPtr = data) { result = Bls384Interop.AggregateVerifyNoCheck(ref aggregateBlsSignature, blsPublicKeys, dataPtr, dataItemLength, publicKeyCount); } } return(result == 1); }
/// <inheritdoc /> public override bool AggregateVerifyHashes(ReadOnlySpan <byte> publicKeys, ReadOnlySpan <byte> hashes, ReadOnlySpan <byte> aggregateSignature, ReadOnlySpan <byte> domain = default) { // This is independent of the keys set, although other parameters (type of curve, variant, scheme, etc) are relevant. if (aggregateSignature.Length != SignatureLength) { throw new ArgumentOutOfRangeException(nameof(aggregateSignature), aggregateSignature.Length, $"Signature must be {SignatureLength} bytes long."); } if (publicKeys.Length % PublicKeyLength != 0) { throw new ArgumentOutOfRangeException(nameof(publicKeys), publicKeys.Length, $"Public key data must be a multiple of the public key length {PublicKeyLength}."); } var publicKeyCount = publicKeys.Length / PublicKeyLength; if (hashes.Length % publicKeyCount != 0) { throw new ArgumentOutOfRangeException(nameof(hashes), hashes.Length, $"Hashes must all be the same length, with total bytes evenly divisible by the number of public keys, {publicKeyCount}."); } EnsureInitialised(); var blsPublicKeys = new Bls384Interop.BlsPublicKey[publicKeyCount]; var publicKeysIndex = 0; for (var blsPublicKeyIndex = 0; blsPublicKeyIndex < publicKeyCount; blsPublicKeyIndex++) { var publicKey = publicKeys.Slice(publicKeysIndex, PublicKeyLength); int publicKeyBytesRead; unsafe { fixed(byte *publicKeyPtr = publicKey) { publicKeyBytesRead = Bls384Interop.PublicKeyDeserialize(ref blsPublicKeys[blsPublicKeyIndex], publicKeyPtr, PublicKeyLength); } } if (publicKeyBytesRead != PublicKeyLength) { throw new Exception( $"Error deserializing BLS public key {blsPublicKeyIndex}, length: {publicKeyBytesRead}"); } publicKeysIndex += PublicKeyLength; } var aggregateBlsSignature = default(Bls384Interop.BlsSignature); int signatureBytesRead; unsafe { fixed(byte *signaturePtr = aggregateSignature) { signatureBytesRead = Bls384Interop.SignatureDeserialize(ref aggregateBlsSignature, signaturePtr, SignatureLength); } } if (signatureBytesRead != aggregateSignature.Length) { throw new Exception($"Error deserializing BLS signature, length: {signatureBytesRead}"); } int result; var hashLength = hashes.Length / publicKeyCount; if (domain.Length > 0) { if (hashLength != HashLength) { throw new ArgumentOutOfRangeException(nameof(hashes), hashes.Length, $"Hashes with domain must have total length {publicKeyCount * HashLength} (each should be {HashLength} bytes long, for {publicKeyCount} public keys)."); } if (domain.Length != DomainLength) { throw new ArgumentOutOfRangeException(nameof(domain), domain.Length, $"Domain must be {DomainLength} bytes long."); } var combined = new Span <byte>(new byte[publicKeyCount * (HashLength + DomainLength)]); var combinedIndex = 0; for (var hashIndex = 0; hashIndex < hashes.Length; hashIndex += HashLength) { var hashSlice = hashes.Slice(hashIndex, HashLength); hashSlice.CopyTo(combined.Slice(combinedIndex)); combinedIndex += HashLength; domain.CopyTo(combined.Slice(combinedIndex)); combinedIndex += DomainLength; } unsafe { fixed(byte *hashPtr = combined) { result = Bls384Interop.VerifyAggregatedHashWithDomain(ref aggregateBlsSignature, blsPublicKeys, hashPtr, publicKeyCount); } } } else { unsafe { fixed(byte *hashPtr = hashes) { result = Bls384Interop.VerifyAggregateHashes(ref aggregateBlsSignature, blsPublicKeys, hashPtr, hashLength, publicKeyCount); } } } return(result == 1); }