Skip to content

Commit 3f73480

Browse files
committed
Writing XMLDocs
1 parent 0ea51e8 commit 3f73480

8 files changed

+413
-9
lines changed

Libplanet.Tests/Crypto/BlsPublicKeyTest.cs

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Libplanet.Crypto;
66
using Xunit;
77
using Xunit.Abstractions;
8+
using CryptoConfig = Libplanet.Crypto.CryptoConfig;
89

910
namespace Libplanet.Tests.Crypto
1011
{
@@ -158,6 +159,8 @@ public void InvalidProofOfPossession()
158159
[Fact]
159160
public void Verify()
160161
{
162+
// TEST NEEDED: Does the infinite public key and infinite signature verification return
163+
// true?
161164
var pubKey = new BlsPublicKey(_key1, new BlsSignature(_key1ProofOfPossession));
162165
var signature = new byte[]
163166
{

Libplanet/Crypto/BlsPrivateKey.cs

+132-3
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,34 @@
99

1010
namespace Libplanet.Crypto
1111
{
12-
public class BlsPrivateKey : IEquatable<BlsPrivateKey>, IECPrivateKey
12+
/// <summary>
13+
/// A secret key pair of
14+
/// <a href="https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/">BLS Signature</a>
15+
/// used in consensus for signing signature.
16+
/// It can create <see cref="BlsSignature"/>, which can be verified corresponding
17+
/// <see cref="Libplanet.Crypto.BlsPublicKey"/> with message. Also <see cref="BlsSignature"/>
18+
/// can be aggregated with another signatures, and can be verified with multiple corresponding
19+
/// <see cref="Libplanet.Crypto.BlsPublicKey"/> by <see cref="BlsSignature.AggregateVerify"/>,
20+
/// <see cref="BlsSignature.FastAggregateVerify"/> or <see cref="BlsSignature.MultiVerify"/>
21+
/// for its use-case. The implementation uses the BLS12_381 curve type with minimal public key
22+
/// size setting, which is the same configuration with Ethereum 2.0 Phase 0.
23+
/// </summary>
24+
/// <remarks>
25+
/// These (and any derived representations, e.g., <see cref="ByteArray"/>)
26+
/// must be kept secret, if they are exposed, an attacker will be able to
27+
/// forge signatures.
28+
/// <para>Every <see cref="PrivateKey"/> object is immutable.</para>
29+
/// </remarks>
30+
/// <seealso cref="Libplanet.Crypto.BlsPublicKey"/>
31+
public sealed class BlsPrivateKey : IEquatable<BlsPrivateKey>, IECPrivateKey
1332
{
1433
private const int KeyByteSize = BLS.SECRETKEY_SERIALIZE_SIZE;
1534
private readonly IReadOnlyList<byte> _privateKey;
1635
private BlsPublicKey? _publicKey;
1736

1837
/// <summary>
19-
/// Instantiates a new random <see cref="BlsPrivateKey"/>.
38+
/// Instantiates a new random <see cref="BlsPrivateKey"/> with CSPRNG (Cryptographically
39+
/// Secure Random Number Generator).
2040
/// </summary>
2141
public BlsPrivateKey()
2242
{
@@ -28,6 +48,8 @@ public BlsPrivateKey()
2848
/// </summary>
2949
/// <param name="privateKey">A <see cref="byte"/> array representation of private key.
3050
/// </param>
51+
/// <exception cref="ArgumentNullException">Thrown if given value is
52+
/// <see cref="ImmutableArray{T}"/> and empty.</exception>
3153
/// <exception cref="ArgumentOutOfRangeException">Thrown if given private key is not
3254
/// <see cref="KeyByteSize"/>.
3355
/// </exception>
@@ -64,7 +86,7 @@ public BlsPrivateKey(string hex)
6486
}
6587

6688
/// <summary>
67-
/// A pair public key of this private key.
89+
/// A pair public key of private key.
6890
/// </summary>
6991
public BlsPublicKey PublicKey
7092
{
@@ -83,9 +105,29 @@ public BlsPublicKey PublicKey
83105

84106
IReadOnlyList<byte> IECPrivateKey.KeyBytes => ByteArray;
85107

108+
/// <summary>
109+
/// The parameter for BLS private key signature. This is not supported.
110+
/// </summary>
111+
/// <exception cref="NotSupportedException">This is not supported.</exception>
86112
public ECPrivateKeyParameters KeyParam => throw new NotSupportedException(
87113
"Currently setting key with BLS key parameter is not supported.");
88114

115+
/// <summary>
116+
/// An encoded <see cref="byte"/> array representation.
117+
/// </summary>
118+
/// <remarks>
119+
/// An encoded <see cref="byte"/> array representation can be recovered to a <see
120+
/// cref="BlsPrivateKey"/> instance again using
121+
/// <see cref="BlsPrivateKey(IReadOnlyList{byte})"/> constructor.
122+
/// <para>As like <see cref="BlsPrivateKey"/> instances, it also must be kept secret.
123+
/// In practice, this must not be sent over the network, and be securely stored in the file
124+
/// system.
125+
/// </para>
126+
/// <para>To get a mutable array instead of immutable one, use <see cref="ToByteArray()"/>
127+
/// method instead.</para>
128+
/// </remarks>
129+
/// <seealso cref="ToByteArray()"/>
130+
/// <seealso cref="PrivateKey(IReadOnlyList{byte})"/>
89131
[Pure]
90132
public ImmutableArray<byte> ByteArray => _privateKey.ToImmutableArray();
91133

@@ -95,10 +137,37 @@ public BlsPublicKey PublicKey
95137
public static bool operator !=(BlsPrivateKey left, BlsPrivateKey right) =>
96138
!left.Equals(right);
97139

140+
/// <summary>
141+
/// Creates a <see cref="BlsPrivateKey"/> instance from hexadecimal string of bytes.
142+
/// </summary>
143+
/// <param name="hex">A hexadecimal string of a private key's
144+
/// <see cref="ByteArray"/>.</param>
145+
/// <returns>A created <see cref="BlsPrivateKey"/> instance.</returns>
146+
/// <exception cref="ArgumentNullException">Thrown when the given <paramref name="hex"/>
147+
/// string is <c>null</c>.</exception>
148+
/// <exception cref="ArgumentOutOfRangeException">Thrown when the length of the given
149+
/// <paramref name="hex"/> string is too short or too long.</exception>
150+
/// <exception cref="FormatException">Thrown when the given <paramref name="hex"/> string is
151+
/// not a valid hexadecimal string.</exception>
152+
/// <exception cref="CryptographicException">Thrown if deserialization has been failed
153+
/// in library.
154+
/// </exception>
98155
[Pure]
99156
public static BlsPrivateKey FromString(string hex) =>
100157
new BlsPrivateKey(GenerateBytesFromHexString(hex));
101158

159+
/// <summary>
160+
/// Returns the corresponding Proof of Possession. Public key can be aggregated, therefore
161+
/// some public key are not the true public key from a private key.
162+
/// <para>The Proof of Possession
163+
/// is used for validate whether the public key is derived from a private key.
164+
/// </para>
165+
/// </summary>
166+
/// <returns>Returns the proof of possession of <see cref="BlsPrivateKey"/>.</returns>
167+
/// <remarks>The infinite public key (e.g., derived from zero private key) cannot be
168+
/// validated with Proof of possession of its infinite signature and considered invalid.
169+
/// Therefore, the infinite public key also can be filtered with proof of possession.
170+
/// </remarks>
102171
[Pure]
103172
public BlsSignature GetProofOfPossession() => PublicKey.ProofOfPossession;
104173

@@ -109,14 +178,74 @@ public bool Equals(BlsPrivateKey? other) =>
109178

110179
public override int GetHashCode() => ByteUtil.CalculateHashCode(ToByteArray());
111180

181+
/// <summary>
182+
/// Creates a signature from the given <paramref name="message"/>.
183+
/// <para>A created signature can be verified by the corresponding
184+
/// <see cref="BlsPublicKey"/>.
185+
/// </para>
186+
/// <para>Signatures can be created by only the <see cref="BlsPrivateKey"/> which
187+
/// corresponds a <see cref="BlsPublicKey"/> to verify these signatures.</para>
188+
/// <para>To sum up, a signature is used to guarantee:</para>
189+
/// <list type="bullet">
190+
/// <item><description>that the <paramref name="message"/> was created by someone possessing
191+
/// the corresponding <see cref="BlsPrivateKey"/>,</description></item>
192+
/// <item><description>that the possessor cannot deny having sent the
193+
/// <paramref name="message"/>, and</description></item>
194+
/// <item><description>that the <paramref name="message"/> was not forged in the middle of
195+
/// transit.</description></item>
196+
/// </list>
197+
/// <see cref="BlsSignature"/> can be aggregated, and can verify multiple signature in
198+
/// batch.
199+
/// <list type="bullet">
200+
/// <item><description>If the messages are all different, use
201+
/// <see cref="BlsSignature.AggregateVerify"/> or,</description></item>
202+
/// <item><description>all the messages are same, use
203+
/// <see cref="BlsSignature.FastAggregateVerify"/></description></item>
204+
/// <item><description>if
205+
/// above all cases are not true, then use <see cref="BlsSignature.MultiVerify"/> without a
206+
/// signature aggregation.</description></item>
207+
/// </list>
208+
/// </summary>
209+
/// <param name="message">A message <see cref="byte"/>s to sign.</param>
210+
/// <returns>A signature that proves the authenticity of the <paramref name="message"/>.
211+
/// It can be verified using <see cref="Libplanet.Crypto.BlsPublicKey.Verify"/>,
212+
/// <see cref="BlsSignature.AggregateVerify"/>,
213+
/// <see cref="BlsSignature.FastAggregateVerify"/>, or
214+
/// <see cref="BlsSignature.MultiVerify"/> method with requiring use-case.
215+
/// </returns>
216+
/// <seealso cref="Libplanet.Crypto.BlsPublicKey.Verify"/>
217+
/// <seealso cref="BlsSignature.AggregateVerify"/>
218+
/// <seealso cref="BlsSignature.FastAggregateVerify"/>
219+
/// <seealso cref="BlsSignature.MultiVerify"/>
112220
public byte[] Sign(byte[] message)
113221
{
114222
HashDigest<SHA256> hashed = HashDigest<SHA256>.DeriveFrom(message);
115223
return CryptoConfig.ConsensusCryptoBackend.Sign(hashed, this);
116224
}
117225

226+
/// <inheritdoc cref="Sign(byte[])"/>
118227
public byte[] Sign(ImmutableArray<byte> message) => Sign(message.ToArray());
119228

229+
/// <summary>
230+
/// Encodes the private key into a corresponding mutable <see cref="byte"/> array
231+
/// representation.
232+
/// </summary>
233+
/// <returns>An encoded <see cref="byte"/> array representation. It guarantees that
234+
/// returned arrays are never reused, and mutating on them does not affect
235+
/// <see cref="BlsPrivateKey"/> instance's internal states.</returns>
236+
/// <remarks>
237+
/// An encoded <see cref="byte"/> array representation can be recovered to a <see
238+
/// cref="BlsPrivateKey"/> instance again using
239+
/// <see cref="BlsPrivateKey(IReadOnlyList{byte})"/> constructor.
240+
/// <para>As like <see cref="BlsPrivateKey"/> instances, it also must be kept secret.
241+
/// In practice, this must not be sent over the network, and be securely stored in the file
242+
/// system.
243+
/// </para>
244+
/// <para>To get an immutable array instead of mutable one, use <see cref="ByteArray"/>
245+
/// property.</para>
246+
/// </remarks>
247+
/// <seealso cref="ByteArray"/>
248+
/// <seealso cref="BlsPrivateKey(IReadOnlyList{byte})"/>
120249
[Pure]
121250
public byte[] ToByteArray() => _privateKey.ToArray();
122251

Libplanet/Crypto/BlsPublicKey.cs

+81-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,44 @@
99

1010
namespace Libplanet.Crypto
1111
{
12-
public class BlsPublicKey : IEquatable<BlsPublicKey>, IECPublicKey
12+
/// <summary>
13+
/// A public key pair of
14+
/// <a href="https://datatracker.ietf.org/doc/draft-irtf-cfrg-bls-signature/">BLS Signature</a>
15+
/// used in consensus for verifying signature.
16+
/// It can verify <see cref="BlsSignature"/>, which can be verified corresponding
17+
/// <see cref="Libplanet.Crypto.BlsPublicKey"/> with message. Also <see cref="BlsSignature"/>
18+
/// can be aggregated with another signatures, and can be verified with multiple corresponding
19+
/// <see cref="Libplanet.Crypto.BlsPublicKey"/> by <see cref="BlsSignature.AggregateVerify"/>,
20+
/// <see cref="BlsSignature.FastAggregateVerify"/> or <see cref="BlsSignature.MultiVerify"/>
21+
/// for its use-case. The implementation uses the BLS12_381 curve type with minimal public key
22+
/// size setting, which is the same configuration with Ethereum 2.0 Phase 0.
23+
/// </summary>
24+
/// <remarks>
25+
/// The <see cref="BlsPublicKey"/> can be published publicly, and this is required to verify the
26+
/// signature from a <see cref="BlsPrivateKey"/>. The received public key from any peer should
27+
/// be checked with <see cref="ProofOfPossession"/> due to the availability of public key
28+
/// aggregation. See
29+
/// <a href="https://datatracker.ietf.org/doc/id/draft-halla
30+
/// mbaker-threshold-sigs-02.html#name-rogue-key-attack">
31+
/// Rouge Key Attack</a>.
32+
/// <para>Every <see cref="BlsPublicKey"/> object is immutable.</para>
33+
/// </remarks>
34+
/// <seealso cref="Libplanet.Crypto.BlsPrivateKey"/>
35+
public sealed class BlsPublicKey : IEquatable<BlsPublicKey>, IECPublicKey
1336
{
1437
private const int KeyByteSize = BLS.PUBLICKEY_SERIALIZE_SIZE;
1538

1639
private readonly IReadOnlyList<byte> _publicKey;
1740

41+
/// <summary>
42+
/// Creates a <see cref="BlsPublicKey"/> instance from the given
43+
/// <see cref="byte"/> array (i.e., <paramref name="publicKey"/>).
44+
/// </summary>
45+
/// <param name="publicKey">A valid <see cref="byte"/> array that
46+
/// encodes an BLS public key.</param>
47+
/// <param name="proofOfPossession">A proof of possession of given public key. The policy
48+
/// does not allow public key aggregation for safety. The every <see cref="BlsPublicKey"/>
49+
/// should be non-aggregated public key, and has a pair <see cref="BlsPrivateKey"/>.</param>
1850
public BlsPublicKey(IReadOnlyList<byte> publicKey, BlsSignature proofOfPossession)
1951
{
2052
if (publicKey is ImmutableArray<byte> i ? i.IsDefaultOrEmpty : !publicKey.Any())
@@ -48,6 +80,18 @@ public BlsPublicKey(IReadOnlyList<byte> publicKey, BlsSignature proofOfPossessio
4880
public ECPublicKeyParameters KeyParam => throw new NotSupportedException(
4981
"Currently setting key with BLS key parameter is not supported.");
5082

83+
/// <summary>
84+
/// Returns the corresponding Proof of Possession. Public key can be aggregated, therefore
85+
/// some public key are not the true public key from a private key.
86+
/// <para>The Proof of Possession
87+
/// is used for validate whether the public key is derived from a private key.
88+
/// </para>
89+
/// </summary>
90+
/// <returns>Returns the proof of possession of <see cref="BlsPublicKey"/>.</returns>
91+
/// <remarks>The infinite public key (e.g., derived from zero private key) cannot be
92+
/// validated with Proof of possession of its infinite signature and considered invalid.
93+
/// Therefore, the infinite public key also can be filtered with proof of possession.
94+
/// </remarks>
5195
[Pure]
5296
public BlsSignature ProofOfPossession { get; }
5397

@@ -64,13 +108,45 @@ public bool Equals(BlsPublicKey? other) =>
64108

65109
public override int GetHashCode() => ByteUtil.CalculateHashCode(ToByteArray());
66110

111+
/// <summary>
112+
/// Encodes this public key into a mutable <see cref="byte"/> array representation.
113+
/// </summary>
114+
/// <returns>An encoded mutable <see cref="byte"/> array representation. It can be
115+
/// recovered to a <see cref="PublicKey"/> instance again using
116+
/// <see cref="BlsPublicKey(IReadOnlyList{byte}, BlsSignature)"/> constructor.</returns>
117+
/// <seealso cref="ToImmutableArray()"/>
118+
/// <seealso cref="BlsPublicKey(IReadOnlyList{byte}, BlsSignature)"/>
67119
[Pure]
68120
public byte[] ToByteArray() => _publicKey.ToArray();
69121

122+
/// <summary>
123+
/// Encodes this public key into a immutable <see cref="byte"/> array representation.
124+
/// <para>To get an mutable one, use <see cref="ToByteArray()"/> method instead.</para>
125+
/// </summary>
126+
/// <returns>An encoded immutable <see cref="byte"/> array representation. It can be
127+
/// recovered to a <see cref="BlsPublicKey"/> instance again using
128+
/// <see cref="BlsPublicKey(IReadOnlyList{byte}, BlsSignature)"/> constructor.</returns>
129+
/// <seealso cref="BlsPublicKey(IReadOnlyList{byte}, BlsSignature)"/>
70130
[Pure]
71131
public ImmutableArray<byte> ToImmutableArray() =>
72132
ToByteArray().ToImmutableArray();
73133

134+
/// <summary>
135+
/// Verifies whether a <paramref name="signature"/> proves authenticity of
136+
/// <paramref name="message"/> with the corresponding <see cref="BlsPrivateKey"/>.
137+
/// <para>If signature is aggregated, use <see cref="BlsSignature.AggregateVerify"/> or
138+
/// <see cref="BlsSignature.FastAggregateVerify"/>.</para>
139+
/// </summary>
140+
/// <param name="message">A original plaintext message that the <paramref name="signature"/>
141+
/// tries to prove its authenticity. I.e., an argument data passed to
142+
/// <see cref="BlsPrivateKey.Sign(byte[])"/> or <see
143+
/// cref="BlsPrivateKey.Sign(ImmutableArray{byte})" /> methods.</param>
144+
/// <param name="signature">A signature which tries to authenticity of
145+
/// <paramref name="message"/>. I.e., a data that <see cref="BlsPrivateKey.Sign(byte[])"/>
146+
/// or <see cref="BlsPrivateKey.Sign(ImmutableArray{byte})"/> methods returned.</param>
147+
/// <returns><c>true</c> if the <paramref name="signature"/> proves authenticity of
148+
/// the <paramref name="message"/> with the corresponding <see cref="BlsPublicKey"/>.
149+
/// Otherwise <c>false</c>.</returns>
74150
[Pure]
75151
public bool Verify(IReadOnlyList<byte> message, IReadOnlyList<byte> signature)
76152
{
@@ -99,6 +175,10 @@ public bool Verify(IReadOnlyList<byte> message, IReadOnlyList<byte> signature)
99175
hashed, signature.ToArray(), this);
100176
}
101177

178+
/// <summary>
179+
/// Gets the public key's hexadecimal representation in compressed form.
180+
/// </summary>
181+
/// <returns>The hexadecimal string of the public key bytes.</returns>
102182
public override string ToString() => ByteUtil.Hex(ToByteArray());
103183
}
104184
}

0 commit comments

Comments
 (0)