/// <inheritdoc /> public override bool VerifyHash(ReadOnlySpan <byte> publicKey, ReadOnlySpan <byte> hash, ReadOnlySpan <byte> signature, ReadOnlySpan <byte> domain = default) { if (signature.Length != SignatureLength) { throw new ArgumentOutOfRangeException(nameof(signature), signature.Length, $"Signature must be {SignatureLength} bytes long."); } EnsureInitialised(); var blsPublicKey = default(Bls384Interop.BlsPublicKey); int publicKeyBytesRead; unsafe { fixed(byte *publicKeyPtr = publicKey) { publicKeyBytesRead = Bls384Interop.PublicKeyDeserialize(ref blsPublicKey, publicKeyPtr, publicKey !.Length); } } if (publicKeyBytesRead != publicKey.Length) { throw new Exception($"Error deserializing BLS public key, length: {publicKeyBytesRead}"); } var blsSignature = default(Bls384Interop.BlsSignature); int signatureBytesRead; unsafe { fixed(byte *signaturePtr = signature) { signatureBytesRead = Bls384Interop.SignatureDeserialize(ref blsSignature, signaturePtr, SignatureLength); } } if (signatureBytesRead != signature.Length) { throw new Exception($"Error deserializing BLS signature, length: {signatureBytesRead}"); } int result; if (domain.Length > 0) { if (hash.Length != HashLength) { throw new ArgumentOutOfRangeException(nameof(hash), hash.Length, $"Hash with domain must be {HashLength} bytes long."); } if (domain.Length != DomainLength) { throw new ArgumentOutOfRangeException(nameof(domain), domain.Length, $"Domain must be {DomainLength} bytes long."); } var hashWithDomain = new Span <byte>(new byte[HashLength + DomainLength]); hash.CopyTo(hashWithDomain); domain.CopyTo(hashWithDomain.Slice(HashLength)); unsafe { fixed(byte *hashPtr = hashWithDomain) { result = Bls384Interop.VerifyHashWithDomain(ref blsSignature, ref blsPublicKey, hashPtr); } } } else { unsafe { fixed(byte *hashPtr = hash) { result = Bls384Interop.VerifyHash(ref blsSignature, ref blsPublicKey, hashPtr, hash.Length); } } } return(result == 1); }