Skip to content

Commit e583eb0

Browse files
committed
Implement ALG_EC_PACE_GM
1 parent d7992b3 commit e583eb0

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

src/main/java/com/licel/jcardsim/crypto/KeyAgreementImpl.java

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ public KeyAgreementImpl(byte algorithm) {
6767
case ALG_DH_PLAIN:
6868
engine = new DHBasicAgreement();
6969
break;
70+
case ALG_EC_PACE_GM:
71+
engine = new ECGMAgreement();
72+
break;
7073
default:
7174
CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
7275
break;
@@ -112,7 +115,7 @@ public short generateSecret(byte[] publicData,
112115
byte[] num = engine.calculateAgreement(ecp).toByteArray();
113116

114117
byte[] result;
115-
if (algorithm != ALG_EC_SVDP_DH_PLAIN_XY) {
118+
if (algorithm != ALG_EC_SVDP_DH_PLAIN_XY && algorithm != ALG_EC_PACE_GM) {
116119
// truncate/zero-pad to field size as per the spec:
117120
int fieldSize = ((ECPrivateKeyImpl) privateKey).getDomainParameters().getCurve().getFieldSize();
118121
result = new byte[(fieldSize + 7) / 8];
@@ -139,7 +142,8 @@ public short generateSecret(byte[] publicData,
139142
return (short) hashResult.length;
140143
case ALG_EC_SVDP_DHC_PLAIN: // no break
141144
case ALG_EC_SVDP_DH_PLAIN: // no break
142-
case ALG_EC_SVDP_DH_PLAIN_XY:
145+
case ALG_EC_SVDP_DH_PLAIN_XY: // no break
146+
case ALG_EC_PACE_GM:
143147
// plain output
144148
Util.arrayCopyNonAtomic(result, (short) 0, secret, secretOffset, (short) result.length);
145149
return (short) result.length;
@@ -168,12 +172,8 @@ public void init(CipherParameters privateKey) {
168172
this.key = (ECPrivateKeyParameters)privateKey;
169173
}
170174

171-
/**
172-
* return the field size for the agreement algorithm in bytes.
173-
*/
174-
@Override
175175
public int getFieldSize() {
176-
throw new UnsupportedOperationException("Not supported yet.");
176+
return (this.key.getParameters().getCurve().getFieldSize() + 7) / 8;
177177
}
178178

179179
public BigInteger calculateAgreement(CipherParameters publicKey) {
@@ -182,4 +182,30 @@ public BigInteger calculateAgreement(CipherParameters publicKey) {
182182
return new BigInteger(1, result.getEncoded(false));
183183
}
184184
}
185+
186+
/**
187+
* BouncyCastle doesn't offer KeyAgreement analogous to <code>ALG_EC_PACE_GM</code>.
188+
* So do it here instead and squeeze the resulting point through byte encoding
189+
* in a BigInteger.
190+
*/
191+
static class ECGMAgreement implements BasicAgreement {
192+
private ECPrivateKeyParameters key;
193+
194+
public ECGMAgreement() {
195+
}
196+
197+
public void init(CipherParameters privateKey) {
198+
this.key = (ECPrivateKeyParameters) privateKey;
199+
}
200+
201+
public int getFieldSize() {
202+
return (this.key.getParameters().getCurve().getFieldSize() + 7) / 8;
203+
}
204+
205+
public BigInteger calculateAgreement(CipherParameters publicKey) {
206+
ECPublicKeyParameters pub = (ECPublicKeyParameters) publicKey;
207+
ECPoint result = this.key.getParameters().getG().multiply(this.key.getD()).add(pub.getQ());
208+
return new BigInteger(1, result.getEncoded(false));
209+
}
210+
}
185211
}

src/test/java/com/licel/jcardsim/crypto/KeyAgreementImplTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public void testGenerateSecretECDH() {
5959
testGenerateSecret(KeyPair.ALG_EC_F2M, KeyBuilder.LENGTH_EC_F2M_113, KeyAgreement.ALG_EC_SVDP_DHC_PLAIN);
6060
testGenerateSecret(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_112, KeyAgreement.ALG_EC_SVDP_DHC);
6161
testGenerateSecret(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_112, KeyAgreement.ALG_EC_SVDP_DHC_PLAIN);
62+
System.out.println("test ecgm");
63+
testGenerateSecret(KeyPair.ALG_EC_F2M, KeyBuilder.LENGTH_EC_F2M_113, KeyAgreement.ALG_EC_PACE_GM);
64+
testGenerateSecret(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_112, KeyAgreement.ALG_EC_PACE_GM);
6265
}
6366

6467
/**
@@ -147,7 +150,8 @@ public void testGenerateSecret(byte keyAlg, short keySize, byte keyAgreementAlg)
147150
assertEquals(secret1Size, (int) Math.ceil(keySize / 8.0));
148151
assertEquals(secret2Size, (int) Math.ceil(keySize / 8.0));
149152
break;
150-
case KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY:
153+
case KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY: // no break
154+
case KeyAgreement.ALG_EC_PACE_GM:
151155
int fieldSize = (int) Math.ceil(keySize / 8.0);
152156
assertEquals(secret1Size, 1 + fieldSize + fieldSize);
153157
assertEquals(secret2Size, 1 + fieldSize + fieldSize);

0 commit comments

Comments
 (0)