Skip to content

Commit 9cb941f

Browse files
gefeilidghgit
authored andcommitted
Pass the test vector of ECCSISigner
1 parent b05a7b5 commit 9cb941f

File tree

9 files changed

+223
-61
lines changed

9 files changed

+223
-61
lines changed

core/src/main/java/org/bouncycastle/crypto/generators/ECCSIKeyPairGenerator.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,14 @@
1616
import org.bouncycastle.crypto.params.ECCSIKeyGenerationParameters;
1717
import org.bouncycastle.crypto.params.ECCSIPrivateKeyParameters;
1818
import org.bouncycastle.crypto.params.ECCSIPublicKeyParameters;
19-
import org.bouncycastle.math.ec.ECCurve;
2019
import org.bouncycastle.math.ec.ECPoint;
2120

2221
public class ECCSIKeyPairGenerator
2322
implements AsymmetricCipherKeyPairGenerator
2423
{
2524
// Initialize NIST P-256 curve
2625
private static final X9ECParameters params = CustomNamedCurves.getByName("secP256r1");
27-
private static final ECCurve curve = params.getCurve();
28-
29-
private static final BigInteger q = ((ECCurve.Fp)curve).getQ();
30-
31-
//BigInteger p = ((ECCurve.Fp)curve).getOrder();
32-
33-
// The subgroup order is available as:
34-
//BigInteger n = params.getN();
26+
private static final BigInteger q = params.getCurve().getOrder();
3527

3628
// And the base point (generator) is:
3729
private static final ECPoint G = params.getG();
@@ -73,6 +65,7 @@ public AsymmetricCipherKeyPair generateKeyPair()
7365

7466
// 4) Compute SSK = ( KSAK + HS * v ) modulo q;
7567
BigInteger ssk = parameters.computeSSK(HS.multiply(v));
76-
return new AsymmetricCipherKeyPair(new ECCSIPublicKeyParameters(pvt), new ECCSIPrivateKeyParameters(ssk));
68+
ECCSIPublicKeyParameters pub = new ECCSIPublicKeyParameters(pvt);
69+
return new AsymmetricCipherKeyPair(new ECCSIPublicKeyParameters(pvt), new ECCSIPrivateKeyParameters(ssk, pub));
7770
}
7871
}

core/src/main/java/org/bouncycastle/crypto/params/ECCSIKeyGenerationParameters.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,22 @@
66
import org.bouncycastle.asn1.x9.X9ECParameters;
77
import org.bouncycastle.crypto.KeyGenerationParameters;
88
import org.bouncycastle.crypto.ec.CustomNamedCurves;
9-
import org.bouncycastle.math.ec.ECCurve;
109
import org.bouncycastle.math.ec.ECPoint;
1110
import org.bouncycastle.util.Arrays;
1211

1312
public class ECCSIKeyGenerationParameters
1413
extends KeyGenerationParameters
1514
{
16-
private static final X9ECParameters params = CustomNamedCurves.getByName("secP256r1");
17-
private static final ECCurve curve = params.getCurve();
15+
private static final BigInteger q;
16+
private static final ECPoint G;
1817

19-
private static final BigInteger q = ((ECCurve.Fp)curve).getQ();
20-
21-
//BigInteger p = ((ECCurve.Fp)curve).getOrder();
22-
23-
// The subgroup order is available as:
24-
//BigInteger n = params.getN();
18+
static
19+
{
20+
X9ECParameters params = CustomNamedCurves.getByName("secP256r1");
21+
q = params.getCurve().getOrder();
22+
G = params.getG();
23+
}
2524

26-
// And the base point (generator) is:
27-
private static final ECPoint G = params.getG();
2825
private final byte[] id;
2926
private final BigInteger ksak;
3027
private final ECPoint kpak;

core/src/main/java/org/bouncycastle/crypto/params/ECCSIPrivateKeyParameters.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,22 @@ public class ECCSIPrivateKeyParameters
66
extends AsymmetricKeyParameter
77
{
88
private final BigInteger ssk;
9-
public ECCSIPrivateKeyParameters(BigInteger ssk)
9+
private final ECCSIPublicKeyParameters pub;
10+
11+
public ECCSIPrivateKeyParameters(BigInteger ssk, ECCSIPublicKeyParameters pub)
1012
{
1113
super(true);
1214
this.ssk = ssk;
15+
this.pub = pub;
16+
}
17+
18+
public ECCSIPublicKeyParameters getPublicKeyParameters()
19+
{
20+
return pub;
21+
}
22+
23+
public BigInteger getSSK()
24+
{
25+
return ssk;
1326
}
1427
}

core/src/main/java/org/bouncycastle/crypto/params/ECCSIPublicKeyParameters.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@ public class ECCSIPublicKeyParameters
66
extends AsymmetricKeyParameter
77
{
88
private final ECPoint pvt;
9+
910
public ECCSIPublicKeyParameters(ECPoint pvt)
1011
{
1112
super(false);
1213
this.pvt = pvt;
1314
}
15+
16+
public final ECPoint getPVT()
17+
{
18+
return pvt;
19+
}
1420
}

core/src/main/java/org/bouncycastle/crypto/params/SAKKEPublicKeyParameters.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public class SAKKEPublicKeyParameters
7777
* Pairing result g = <P,P> computed using the Tate-Lichtenbaum pairing
7878
* (RFC 6508, Section 3.2). Value from RFC 6509 Appendix A.
7979
*/
80-
private static final BigInteger g = new BigInteger(Hex.decode("66FC2A43 2B6EA392 148F1586 7D623068\n" +
80+
private static final BigInteger g = new BigInteger(1, Hex.decode("66FC2A43 2B6EA392 148F1586 7D623068\n" +
8181
" C6A87BD1 FB94C41E 27FABE65 8E015A87\n" +
8282
" 371E9474 4C96FEDA 449AE956 3F8BC446\n" +
8383
" CBFDA85D 5D00EF57 7072DA8F 541721BE\n" +

core/src/main/java/org/bouncycastle/crypto/signers/ECCSISigner.java

Lines changed: 117 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.bouncycastle.crypto.signers;
22

3+
import java.io.ByteArrayOutputStream;
34
import java.math.BigInteger;
45
import java.security.SecureRandom;
56

@@ -12,92 +13,173 @@
1213
import org.bouncycastle.crypto.digests.SHA256Digest;
1314
import org.bouncycastle.crypto.ec.CustomNamedCurves;
1415
import org.bouncycastle.crypto.params.ECCSIPrivateKeyParameters;
16+
import org.bouncycastle.crypto.params.ECCSIPublicKeyParameters;
1517
import org.bouncycastle.crypto.params.ParametersWithRandom;
16-
import org.bouncycastle.math.ec.ECCurve;
1718
import org.bouncycastle.math.ec.ECPoint;
19+
import org.bouncycastle.util.Arrays;
1820
import org.bouncycastle.util.BigIntegers;
1921

2022
public class ECCSISigner
2123
implements Signer
2224
{
23-
private static final X9ECParameters params = CustomNamedCurves.getByName("secP256r1");
24-
private static final ECCurve curve = params.getCurve();
25+
private static final BigInteger q;
26+
private static final ECPoint G;
2527

26-
private static final BigInteger q = ((ECCurve.Fp)curve).getQ();
27-
28-
//BigInteger p = ((ECCurve.Fp)curve).getOrder();
29-
30-
// The subgroup order is available as:
31-
//BigInteger n = params.getN();
28+
static
29+
{
30+
X9ECParameters params = CustomNamedCurves.getByName("secP256r1");
31+
q = params.getCurve().getOrder();
32+
G = params.getG();
33+
}
3234

33-
// And the base point (generator) is:
34-
private static final ECPoint G = params.getG();
3535
private final Digest digest = new SHA256Digest();
36-
BigInteger j;
37-
ECPoint J;
38-
BigInteger r;
39-
40-
public ECCSISigner()
36+
private BigInteger j;
37+
private BigInteger r;
38+
private ECPoint Y;
39+
private final ECPoint kpak;
40+
private final byte[] id;
41+
private CipherParameters param;
42+
private ByteArrayOutputStream stream;
43+
private boolean forSigning;
44+
45+
public ECCSISigner(ECPoint kpak, byte[] id)
4146
{
42-
47+
this.kpak = kpak;
48+
this.id = id;
4349
}
4450

4551
@Override
4652
public void init(boolean forSigning, CipherParameters param)
4753
{
54+
this.forSigning = forSigning;
55+
this.param = param;
4856
SecureRandom random = null;
4957
if (param instanceof ParametersWithRandom)
5058
{
5159
random = ((ParametersWithRandom)param).getRandom();
5260
param = ((ParametersWithRandom)param).getParameters();
5361
}
54-
62+
ECPoint kpak_computed = null;
63+
ECPoint pvt;
5564
if (forSigning)
5665
{
5766
ECCSIPrivateKeyParameters parameters = (ECCSIPrivateKeyParameters)param;
5867

5968
j = new BigInteger(256, random).mod(q);
60-
J = G.multiply(j).normalize();
69+
ECPoint J = G.multiply(j).normalize();
6170
r = J.getAffineXCoord().toBigInteger();
62-
byte[] rBytes = BigIntegers.asUnsignedByteArray(256, r);
63-
// BigInteger kpak = parameters
64-
byte[] tmp = G.getEncoded(false);
65-
digest.update(tmp, 0, tmp.length);
66-
// tmp = kpak.getEncoded(false);
67-
// digest.update(tmp, 0, tmp.length);
68-
// digest.update(id, 0, id.length);
69-
// tmp = pvt.getEncoded(false);
70-
// digest.update(tmp, 0, tmp.length);
71-
tmp = new byte[digest.getDigestSize()];
72-
digest.doFinal(tmp, 0);
73-
BigInteger HS = new BigInteger(1, tmp).mod(q);
71+
pvt = parameters.getPublicKeyParameters().getPVT();
72+
kpak_computed = G.multiply(parameters.getSSK());
73+
}
74+
else
75+
{
76+
ECCSIPublicKeyParameters parameters = (ECCSIPublicKeyParameters)param;
77+
pvt = parameters.getPVT();
78+
stream = new ByteArrayOutputStream();
7479
}
7580

81+
// compute HS
82+
byte[] tmp = G.getEncoded(false);
83+
digest.update(tmp, 0, tmp.length);
84+
tmp = kpak.getEncoded(false);
85+
digest.update(tmp, 0, tmp.length);
86+
digest.update(id, 0, id.length);
87+
tmp = pvt.getEncoded(false);
88+
digest.update(tmp, 0, tmp.length);
89+
tmp = new byte[digest.getDigestSize()];
90+
digest.doFinal(tmp, 0);
91+
BigInteger HS = new BigInteger(1, tmp).mod(q);
92+
93+
//HE = hash( HS || r || M );
94+
digest.update(tmp, 0, tmp.length);
95+
if (forSigning)
96+
{
97+
kpak_computed = kpak_computed.subtract(pvt.multiply(HS)).normalize();
98+
if (!kpak_computed.equals(kpak))
99+
{
100+
throw new IllegalArgumentException("Invalid KPAK");
101+
}
102+
byte[] rBytes = BigIntegers.asUnsignedByteArray(32, r);
103+
digest.update(rBytes, 0, rBytes.length);
104+
}
105+
else
106+
{
107+
// Compute Y = HS*PVT + KPAK
108+
Y = pvt.multiply(HS).add(kpak).normalize();
109+
}
76110
}
77111

78112
@Override
79113
public void update(byte b)
80114
{
81-
115+
if (forSigning)
116+
{
117+
digest.update(b);
118+
}
119+
else
120+
{
121+
stream.write(b);
122+
}
82123
}
83124

84125
@Override
85126
public void update(byte[] in, int off, int len)
86127
{
87-
128+
if (forSigning)
129+
{
130+
digest.update(in, off, len);
131+
}
132+
else
133+
{
134+
stream.write(in, off, len);
135+
}
88136
}
89137

90138
@Override
91139
public byte[] generateSignature()
92140
throws CryptoException, DataLengthException
93141
{
94-
return new byte[0];
142+
byte[] heBytes = new byte[digest.getDigestSize()];
143+
digest.doFinal(heBytes, 0);
144+
145+
//Compute s' = ( (( HE + r * SSK )^-1) * j ) modulo q
146+
ECCSIPrivateKeyParameters params = (ECCSIPrivateKeyParameters)(((ParametersWithRandom)param).getParameters());
147+
BigInteger ssk = params.getSSK();
148+
BigInteger denominator = new BigInteger(1, heBytes).add(r.multiply(ssk)).mod(q);
149+
if (denominator.equals(BigInteger.ZERO))
150+
{
151+
throw new IllegalArgumentException("Invalid j, retry");
152+
}
153+
154+
BigInteger sPrime = denominator.modInverse(q).multiply(j).mod(q);
155+
156+
return Arrays.concatenate(BigIntegers.asUnsignedByteArray(32, r), BigIntegers.asUnsignedByteArray(32, sPrime),
157+
params.getPublicKeyParameters().getPVT().getEncoded(false));
95158
}
96159

97160
@Override
98161
public boolean verifySignature(byte[] signature)
99162
{
100-
return false;
163+
byte[] bytes = Arrays.copyOf(signature, 32);
164+
BigInteger s = new BigInteger(1, Arrays.copyOfRange(signature, 32, 64));
165+
r = new BigInteger(1, bytes).mod(q);
166+
digest.update(bytes, 0, 32);
167+
bytes = stream.toByteArray();
168+
digest.update(bytes, 0, bytes.length);
169+
bytes = new byte[digest.getDigestSize()];
170+
digest.doFinal(bytes, 0);
171+
172+
BigInteger HE = new BigInteger(1, bytes).mod(q);
173+
174+
// Compute J = s*(HE*G + r*Y)
175+
ECPoint HE_G = G.multiply(HE).normalize();
176+
ECPoint rY = Y.multiply(r).normalize();
177+
ECPoint sum = HE_G.add(rY).normalize();
178+
ECPoint J = sum.multiply(s).normalize();
179+
180+
BigInteger rComputed = J.getAffineXCoord().toBigInteger();
181+
182+
return rComputed.mod(q).equals(r.mod(q));
101183
}
102184

103185
@Override

0 commit comments

Comments
 (0)