public override bool TryAggregatePublicKeys(ReadOnlySpan <byte> publicKeys, Span <byte> destination, out int bytesWritten) { // This is independent of the keys set, although other parameters (type of curve, variant, scheme, etc) are relevant. 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}."); } if (destination.Length < PublicKeyLength) { bytesWritten = 0; return(false); } EnsureInitialised(); var aggregateBlsPublicKey = default(Bls384Interop.BlsPublicKey); for (var index = 0; index < publicKeys.Length; index += PublicKeyLength) { var publicKeySlice = publicKeys.Slice(index, PublicKeyLength); var blsPublicKey = default(Bls384Interop.BlsPublicKey); int publicKeyBytesRead; unsafe { // Using fixed pointer for input data allows us to pass a slice fixed(byte *publicKeyPtr = publicKeySlice) { publicKeyBytesRead = Bls384Interop.PublicKeyDeserialize(ref blsPublicKey, publicKeyPtr, PublicKeyLength); } } if (publicKeyBytesRead != PublicKeyLength) { throw new Exception($"Error deserializing BLS public key, length: {publicKeyBytesRead}"); } if (index == 0) { aggregateBlsPublicKey = blsPublicKey; } else { Bls384Interop.PublicKeyAdd(ref aggregateBlsPublicKey, ref blsPublicKey); } } unsafe { // Using fixed pointer for output data allows us to write directly to destination fixed(byte *destinationPtr = destination) { bytesWritten = Bls384Interop.PublicKeySerialize(destinationPtr, PublicKeyLength, ref aggregateBlsPublicKey); } } if (bytesWritten != PublicKeyLength) { throw new Exception($"Error serializing BLS public key, length: {bytesWritten}"); } return(true); }
private void EnsurePublicKey() { if (_publicKey == null) { if (_privateKey != null) { EnsureInitialised(); // Standard values are big endian encoding (are using the Herumi deserialize / serialize) var blsSecretKey = default(Bls384Interop.BlsSecretKey); int bytesRead; unsafe { fixed(byte *ptr = _privateKey) { bytesRead = Bls384Interop.SecretKeyDeserialize(ref blsSecretKey, ptr, _privateKey.Length); } } if (bytesRead != _privateKey.Length) { throw new Exception($"Error deserializing BLS private key, length: {bytesRead}"); } var blsPublicKey = default(Bls384Interop.BlsPublicKey); Bls384Interop.GetPublicKey(ref blsPublicKey, ref blsSecretKey); var buffer = new Span <byte>(new byte[PublicKeyLength]); int bytesWritten; unsafe { fixed(byte *ptr = buffer) { bytesWritten = Bls384Interop.PublicKeySerialize(ptr, buffer.Length, ref blsPublicKey); } } if (bytesWritten != buffer.Length) { throw new Exception($"Error serializing BLS public key, length: {bytesWritten}"); } _publicKey = buffer.ToArray(); } } }