Skip to content

Commit 196797d

Browse files
committed
Support signer reuse in SM2Signer
1 parent 5ad15ee commit 196797d

File tree

2 files changed

+95
-9
lines changed

2 files changed

+95
-9
lines changed

crypto/src/crypto/signers/SM2Signer.cs

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,18 @@ namespace Org.BouncyCastle.Crypto.Signers
1515
public class SM2Signer
1616
: ISigner
1717
{
18+
private enum State
19+
{
20+
Uninitialized = 0,
21+
Init = 1,
22+
Data = 2,
23+
}
24+
1825
private readonly IDsaKCalculator kCalculator = new RandomDsaKCalculator();
1926
private readonly IDigest digest;
2027
private readonly IDsaEncoding encoding;
2128

29+
private State m_state = State.Uninitialized;
2230
private ECDomainParameters ecParams;
2331
private ECPoint pubPoint;
2432
private ECKeyParameters ecKey;
@@ -100,23 +108,28 @@ public virtual void Init(bool forSigning, ICipherParameters parameters)
100108

101109
digest.Reset();
102110
z = GetZ(userID);
103-
104-
digest.BlockUpdate(z, 0, z.Length);
111+
m_state = State.Init;
105112
}
106113

107114
public virtual void Update(byte b)
108115
{
116+
CheckData();
117+
109118
digest.Update(b);
110119
}
111120

112121
public virtual void BlockUpdate(byte[] input, int inOff, int inLen)
113122
{
123+
CheckData();
124+
114125
digest.BlockUpdate(input, inOff, inLen);
115126
}
116127

117128
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
118129
public virtual void BlockUpdate(ReadOnlySpan<byte> input)
119130
{
131+
CheckData();
132+
120133
digest.BlockUpdate(input);
121134
}
122135
#endif
@@ -125,6 +138,8 @@ public virtual void BlockUpdate(ReadOnlySpan<byte> input)
125138

126139
public virtual byte[] GenerateSignature()
127140
{
141+
CheckData();
142+
128143
byte[] eHash = DigestUtilities.DoFinal(digest);
129144

130145
BigInteger n = ecParams.N;
@@ -169,10 +184,16 @@ public virtual byte[] GenerateSignature()
169184
{
170185
throw new CryptoException("unable to encode signature: " + ex.Message, ex);
171186
}
187+
finally
188+
{
189+
Reset();
190+
}
172191
}
173192

174193
public virtual bool VerifySignature(byte[] signature)
175194
{
195+
CheckData();
196+
176197
try
177198
{
178199
BigInteger[] rs = encoding.Decode(ecParams.N, signature);
@@ -182,17 +203,28 @@ public virtual bool VerifySignature(byte[] signature)
182203
catch (Exception)
183204
{
184205
}
206+
finally
207+
{
208+
Reset();
209+
}
185210

186211
return false;
187212
}
188213

189214
public virtual void Reset()
190215
{
191-
if (z != null)
216+
switch (m_state)
192217
{
193-
digest.Reset();
194-
digest.BlockUpdate(z, 0, z.Length);
218+
case State.Init:
219+
return;
220+
case State.Data:
221+
break;
222+
default:
223+
throw new InvalidOperationException(AlgorithmName + " needs to be initialized");
195224
}
225+
226+
digest.Reset();
227+
m_state = State.Init;
196228
}
197229

198230
private bool VerifySignature(BigInteger r, BigInteger s)
@@ -226,7 +258,25 @@ private bool VerifySignature(BigInteger r, BigInteger s)
226258
return false;
227259

228260
// B7
229-
return r.Equals(e.Add(x1y1.AffineXCoord.ToBigInteger()).Mod(n));
261+
BigInteger expectedR = e.Add(x1y1.AffineXCoord.ToBigInteger()).Mod(n);
262+
263+
return expectedR.Equals(r);
264+
}
265+
266+
private void CheckData()
267+
{
268+
switch (m_state)
269+
{
270+
case State.Init:
271+
break;
272+
case State.Data:
273+
return;
274+
default:
275+
throw new InvalidOperationException(AlgorithmName + " needs to be initialized");
276+
}
277+
278+
digest.BlockUpdate(z, 0, z.Length);
279+
m_state = State.Data;
230280
}
231281

232282
private byte[] GetZ(byte[] userID)

crypto/test/src/crypto/test/SM2SignerTest.cs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
using System;
2-
using System.IO;
3-
41
using NUnit.Framework;
52

63
using Org.BouncyCastle.Asn1;
@@ -135,6 +132,12 @@ private void DoSignerTest(string curveName, IDigest d, string ident, string msg,
135132
}
136133

137134
private void DoSignerTest(ECDomainParameters domainParams, IDigest d, string ident, string msg, string x, string nonce, string r, string s)
135+
{
136+
ImplSignerTest(domainParams, d, ident, msg, x, nonce, r, s);
137+
ImplSignerTestReuse(domainParams, d, ident, msg, x);
138+
}
139+
140+
private void ImplSignerTest(ECDomainParameters domainParams, IDigest d, string ident, string msg, string x, string nonce, string r, string s)
138141
{
139142
byte[] idBytes = Strings.ToByteArray(ident);
140143
byte[] msgBytes = Strings.ToByteArray(msg);
@@ -162,6 +165,39 @@ private void DoSignerTest(ECDomainParameters domainParams, IDigest d, string ide
162165
IsTrue("verification failed", signer.VerifySignature(sig));
163166
}
164167

168+
private void ImplSignerTestReuse(ECDomainParameters domainParams, IDigest d, string ident, string msg, string x)
169+
{
170+
byte[] idBytes = Strings.ToByteArray(ident);
171+
byte[] msgBytes = Strings.ToByteArray(msg);
172+
AsymmetricCipherKeyPair kp = GenerateKeyPair(domainParams, x);
173+
174+
SM2Signer signer = new SM2Signer(d);
175+
176+
signer.Init(true, new ParametersWithID(kp.Private, idBytes));
177+
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
178+
byte[] sig1 = signer.GenerateSignature();
179+
180+
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
181+
byte[] sig2 = signer.GenerateSignature();
182+
183+
signer.Update(0x00);
184+
signer.Reset();
185+
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
186+
byte[] sig3 = signer.GenerateSignature();
187+
188+
signer.Init(false, new ParametersWithID(kp.Public, idBytes));
189+
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
190+
IsTrue("verification failed", signer.VerifySignature(sig1));
191+
192+
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
193+
IsTrue("verification failed", signer.VerifySignature(sig2));
194+
195+
signer.Update(0x00);
196+
signer.Reset();
197+
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
198+
IsTrue("verification failed", signer.VerifySignature(sig3));
199+
}
200+
165201
private void DoVerifyBoundsCheck()
166202
{
167203
ECDomainParameters domainParams = ParametersF2m;

0 commit comments

Comments
 (0)