Skip to content

Commit

Permalink
add partial sign3 profiling
Browse files Browse the repository at this point in the history
  • Loading branch information
dufkan committed Jul 8, 2024
1 parent 6792b47 commit d093fd3
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 1 deletion.
5 changes: 5 additions & 0 deletions applet/src/main/java/jc2pecdsa/Consts.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ public class Consts {
public static final byte INS_SIGN2 = (byte) 0x02;
public static final byte INS_SIGN3 = (byte) 0x03;

public static final byte INS_SIGN3_BEFORE_MODEXP = (byte) 0xd0;
public static final byte INS_SIGN3_MODEXP = (byte) 0xd1;
public static final byte INS_SIGN3_BEFORE_DIVIDE = (byte) 0xd2;
public static final byte INS_SIGN3_DIVIDE = (byte) 0xd3;

public final static short E_ALREADY_INITIALIZED = (short) 0xee00;

public final static short SW_Exception = (short) 0xff01;
Expand Down
46 changes: 46 additions & 0 deletions applet/src/main/java/jc2pecdsa/JC2pECDSA.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,19 @@ public void process(APDU apdu) {
case Consts.INS_SIGN3:
sign3(apdu);
break;
// DEBUG INSTRUCTIONS
case Consts.INS_SIGN3_BEFORE_MODEXP:
sign3beforeModExp(apdu);
break;
case Consts.INS_SIGN3_MODEXP:
sign3modExp(apdu);
break;
case Consts.INS_SIGN3_BEFORE_DIVIDE:
sign3beforeDivide(apdu);
break;
case Consts.INS_SIGN3_DIVIDE:
sign3divide(apdu);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
Expand Down Expand Up @@ -185,6 +198,7 @@ private void sign2(APDU apdu) {
Util.arrayCopyNonAtomic(proof, (short) 0, apdu.getBuffer(), (short) 0, (short) 64);
apdu.setOutgoingAndSend((short) 0, (short) (64 + 65));
}

private void sign3(APDU apdu) {
byte[] apduBuffer = loadApdu(apdu);

Expand Down Expand Up @@ -215,6 +229,38 @@ private void sign3(APDU apdu) {
apdu.setOutgoingAndSend((short) 0, (short) 70);
}

private void sign3beforeModExp(APDU apdu) {
byte[] apduBuffer = loadApdu(apdu);
apdu.setOutgoingAndSend((short) 0, (short) 70);
}

private void sign3modExp(APDU apdu) {
byte[] apduBuffer = loadApdu(apdu);
nsqExp.doFinal(apduBuffer, apdu.getOffsetCdata(), (short) 512, apduBuffer, apdu.getOffsetCdata());
apdu.setOutgoingAndSend((short) 0, (short) 70);
}

private void sign3beforeDivide(APDU apdu) {
byte[] apduBuffer = loadApdu(apdu);

nsqExp.doFinal(apduBuffer, apdu.getOffsetCdata(), (short) 512, apduBuffer, apdu.getOffsetCdata());

bn.fromByteArray(apduBuffer, apdu.getOffsetCdata(), (short) 512);
bn.decrement();
apdu.setOutgoingAndSend((short) 0, (short) 70);
}

private void sign3divide(APDU apdu) {
byte[] apduBuffer = loadApdu(apdu);

nsqExp.doFinal(apduBuffer, apdu.getOffsetCdata(), (short) 512, apduBuffer, apdu.getOffsetCdata());

bn.fromByteArray(apduBuffer, apdu.getOffsetCdata(), (short) 512);
bn.decrement();
bn.divide(n);
apdu.setOutgoingAndSend((short) 0, (short) 70);
}

private byte[] loadApdu(APDU apdu) {
byte[] apduBuffer = apdu.getBuffer();
short recvLen = (short) (apdu.setIncomingAndReceive() + apdu.getOffsetCdata());
Expand Down
89 changes: 88 additions & 1 deletion applet/src/test/java/tests/AppletTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public AppletTest() {

@Test
public void testSign() throws Exception {
PrintWriter file = new PrintWriter(new FileWriter("full.csv", false));
PrintWriter file = new PrintWriter(new FileWriter("sign.csv", false));

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
ProtocolManager pm = new ProtocolManager(connect());
Expand Down Expand Up @@ -90,4 +90,91 @@ public void testSign() throws Exception {

file.close();
}

@Test
public void measure() throws Exception {
PrintWriter file = new PrintWriter(new FileWriter("measurement.csv", false));

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
ProtocolManager pm = new ProtocolManager(connect());

BigInteger order = ProtocolManager.G.getCurve().getOrder();
BigInteger m = ProtocolManager.hash(new byte[32]);

BigInteger x1 = ProtocolManager.randomBigInt(32);
BigInteger x2 = ProtocolManager.randomBigInt(32);
ECPoint X = ProtocolManager.G.multiply(x1).multiply(x2);

BigInteger p = new BigInteger(1, new byte[]{(byte) 0xe0, (byte) 0xb6, (byte) 0xa1, (byte) 0xfc, (byte) 0x89, (byte) 0xcb, (byte) 0xcb, (byte) 0xf8, (byte) 0xf6, (byte) 0xdf, (byte) 0xa5, (byte) 0x06, (byte) 0x12, (byte) 0x68, (byte) 0x9e, (byte) 0x2b, (byte) 0xcc, (byte) 0x32, (byte) 0xe5, (byte) 0x81, (byte) 0xeb, (byte) 0x6c, (byte) 0xe4, (byte) 0xb7, (byte) 0x0d, (byte) 0x79, (byte) 0x26, (byte) 0xc2, (byte) 0x97, (byte) 0x3d, (byte) 0xd8, (byte) 0x02, (byte) 0x47, (byte) 0x1e, (byte) 0x09, (byte) 0xcf, (byte) 0x83, (byte) 0x93, (byte) 0xd0, (byte) 0x30, (byte) 0x1f, (byte) 0xbb, (byte) 0x98, (byte) 0x0d, (byte) 0x11, (byte) 0xfd, (byte) 0xd0, (byte) 0xcd, (byte) 0xbd, (byte) 0xc2, (byte) 0xc6, (byte) 0x50, (byte) 0xf7, (byte) 0xd9, (byte) 0x9c, (byte) 0x64, (byte) 0x93, (byte) 0xb6, (byte) 0x7f, (byte) 0xf4, (byte) 0x49, (byte) 0xb4, (byte) 0x08, (byte) 0x4e, (byte) 0x04, (byte) 0xa7, (byte) 0x7e, (byte) 0x32, (byte) 0x79, (byte) 0x2b, (byte) 0xe1, (byte) 0x22, (byte) 0x8f, (byte) 0xae, (byte) 0xdc, (byte) 0xd3, (byte) 0x32, (byte) 0xcf, (byte) 0x57, (byte) 0x31, (byte) 0x93, (byte) 0x1c, (byte) 0x8f, (byte) 0xe0, (byte) 0x26, (byte) 0x15, (byte) 0x87, (byte) 0x13, (byte) 0x88, (byte) 0xc2, (byte) 0xcb, (byte) 0xc2, (byte) 0x6a, (byte) 0x04, (byte) 0x07, (byte) 0x53, (byte) 0xf0, (byte) 0x44, (byte) 0xdb, (byte) 0x23, (byte) 0xb9, (byte) 0x0d, (byte) 0x37, (byte) 0xb0, (byte) 0x5a, (byte) 0xba, (byte) 0x04, (byte) 0x90, (byte) 0x6a, (byte) 0xc1, (byte) 0x3b, (byte) 0xd4, (byte) 0x58, (byte) 0x3f, (byte) 0x25, (byte) 0x08, (byte) 0x14, (byte) 0x25, (byte) 0x64, (byte) 0xbb, (byte) 0xcd, (byte) 0xf5, (byte) 0x67, (byte) 0x38, (byte) 0xc2, (byte) 0x51, (byte) 0x5b, (byte) 0x8b});
BigInteger q = new BigInteger(1, new byte[]{(byte) 0x41, (byte) 0x20, (byte) 0xd0, (byte) 0xcf, (byte) 0x15, (byte) 0xfa, (byte) 0x22, (byte) 0xe2, (byte) 0x11, (byte) 0x1a, (byte) 0x61, (byte) 0x32, (byte) 0x75, (byte) 0x30, (byte) 0x17, (byte) 0x7e, (byte) 0xc3, (byte) 0xf3, (byte) 0x28, (byte) 0x87, (byte) 0x5a, (byte) 0x30, (byte) 0xe6, (byte) 0xb5, (byte) 0xd0, (byte) 0x8c, (byte) 0x45, (byte) 0x55, (byte) 0x98, (byte) 0x27, (byte) 0x57, (byte) 0xe8, (byte) 0xbd, (byte) 0xab, (byte) 0xa0, (byte) 0x4c, (byte) 0xf5, (byte) 0xe9, (byte) 0x06, (byte) 0x8a, (byte) 0xc7, (byte) 0x76, (byte) 0x1c, (byte) 0x2b, (byte) 0x8c, (byte) 0x30, (byte) 0x86, (byte) 0xa0, (byte) 0xc7, (byte) 0xde, (byte) 0xfd, (byte) 0x41, (byte) 0x5e, (byte) 0x44, (byte) 0xf9, (byte) 0x7a, (byte) 0x52, (byte) 0xc8, (byte) 0xb3, (byte) 0xae, (byte) 0xf8, (byte) 0x57, (byte) 0x35, (byte) 0x10, (byte) 0x67, (byte) 0x35, (byte) 0x35, (byte) 0xf3, (byte) 0x0d, (byte) 0x65, (byte) 0xd3, (byte) 0x98, (byte) 0x7a, (byte) 0x4b, (byte) 0x93, (byte) 0xe9, (byte) 0xeb, (byte) 0x6f, (byte) 0x09, (byte) 0x64, (byte) 0x00, (byte) 0x24, (byte) 0x0f, (byte) 0x71, (byte) 0xa5, (byte) 0x8c, (byte) 0x8c, (byte) 0x3b, (byte) 0x2b, (byte) 0xf2, (byte) 0x2f, (byte) 0x83, (byte) 0x46, (byte) 0x7f, (byte) 0x87, (byte) 0x5d, (byte) 0xd7, (byte) 0x34, (byte) 0x12, (byte) 0x8d, (byte) 0x0b, (byte) 0xc3, (byte) 0xb0, (byte) 0x5e, (byte) 0x3e, (byte) 0x0c, (byte) 0x82, (byte) 0x6f, (byte) 0x1a, (byte) 0x69, (byte) 0xa2, (byte) 0x67, (byte) 0x26, (byte) 0x90, (byte) 0xd3, (byte) 0x9b, (byte) 0x11, (byte) 0x17, (byte) 0x20, (byte) 0x56, (byte) 0xe4, (byte) 0x46, (byte) 0x54, (byte) 0xe8, (byte) 0xf9, (byte) 0xa8, (byte) 0xb4, (byte) 0x93});
BigInteger n = p.multiply(q);
BigInteger nsq = n.multiply(n);
BigInteger g = n.add(BigInteger.ONE);
BigInteger lambda = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
BigInteger mu = lambda.modInverse(n);

BigInteger cx2 = g.modPow(x2, nsq).multiply(ProtocolManager.randomBigInt(256).modPow(n, nsq)).mod(nsq);
BigInteger pt = cx2.modPow(lambda, nsq).subtract(BigInteger.ONE).divide(n).multiply(mu).mod(n);
assert pt.equals(x2);

pm.setup(n, nsq, lambda, mu, X);

for(int i = 0; i < 10; ++i) {
// Host sends m to card
byte[] comm = pm.sign1(new byte[32]);
file.printf("%d,", pm.cm.getLastTransmitTime());

// Card sends commitment to host
BigInteger k1 = ProtocolManager.randomBigInt(32);
ECPoint R1 = ProtocolManager.G.multiply(k1);

// Host sends pi1, R1 to card
BigInteger proof1r = ProtocolManager.randomBigInt(32);
ECPoint proof1R = ProtocolManager.G.multiply(proof1r);
BigInteger proof1e = ProtocolManager.hash(proof1R.getEncoded(false));
BigInteger proof1s = proof1r.subtract(proof1e.multiply(k1)).mod(order);

byte[] resp = pm.sign2(proof1e, proof1s, R1);
file.printf("%d,", pm.cm.getLastTransmitTime());
// Card sends pi2, R2 to host
Assertions.assertArrayEquals(ProtocolManager.encodeBigInteger(ProtocolManager.hash(resp)), comm);
byte[] proof2 = Arrays.copyOfRange(resp, 0, 64);
BigInteger proof2e = new BigInteger(1, Arrays.copyOfRange(proof2, 0, 32));
BigInteger proof2s = new BigInteger(1, Arrays.copyOfRange(proof2, 32, 64));
ECPoint R2 = ProtocolManager.G.getCurve().decodePoint(Arrays.copyOfRange(resp, 64, 64 + 65));

ECPoint proof2R = ProtocolManager.G.multiply(proof2s).add(R2.multiply(proof2e));
Assertions.assertEquals(ProtocolManager.hash(proof2R.getEncoded(false)), proof2e);

ECPoint R = R2.multiply(k1);
BigInteger Rx = R.normalize().getRawXCoord().toBigInteger();

BigInteger rho = ProtocolManager.randomBigInt(128);
BigInteger rtilda = ProtocolManager.randomBigInt(256);
BigInteger c1_prime = rho.multiply(order).add(k1.modInverse(order).multiply(m).mod(order)).mod(rtilda);
BigInteger c1 = g.modPow(c1_prime, nsq).multiply(ProtocolManager.randomBigInt(256).modPow(n, nsq)).mod(nsq);
BigInteger v = k1.modInverse(order).multiply(Rx).multiply(x1).mod(order);
BigInteger c2 = cx2.modPow(v, nsq);
BigInteger cs1 = c1.multiply(c2).mod(nsq);

pm.sign3beforeModExp(cs1);
file.printf("%d,", pm.cm.getLastTransmitTime());

pm.sign3modExp(cs1);
file.printf("%d,", pm.cm.getLastTransmitTime());

pm.sign3beforeDivide(cs1);
file.printf("%d,", pm.cm.getLastTransmitTime());

pm.sign3divide(cs1);
file.printf("%d,", pm.cm.getLastTransmitTime());

// Host sends cs1 to card
byte[] signature = pm.sign3(cs1);
file.printf("%d\n", pm.cm.getLastTransmitTime());
Assertions.assertTrue(ProtocolManager.verifySignature(X, new byte[32], signature));
}

file.close();
}
}
53 changes: 53 additions & 0 deletions applet/src/test/java/tests/ProtocolManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,59 @@ public byte[] sign3(BigInteger cs1) throws Exception {
return responseAPDU.getData();
}

public byte[] sign3beforeModExp(BigInteger cs1) throws Exception {
CommandAPDU cmd = new CommandAPDU(
Consts.CLA_JC2PECDSA,
Consts.INS_SIGN3_BEFORE_MODEXP,
0,
0,
ProtocolManager.encodeBigInteger(cs1, 512)
);
ResponseAPDU responseAPDU = cm.transmit(cmd);
Assertions.assertNotNull(responseAPDU);
Assertions.assertEquals(ISO7816.SW_NO_ERROR & 0xffff, responseAPDU.getSW());
return responseAPDU.getData();
}

public void sign3modExp(BigInteger cs1) throws Exception {
CommandAPDU cmd = new CommandAPDU(
Consts.CLA_JC2PECDSA,
Consts.INS_SIGN3_MODEXP,
0,
0,
ProtocolManager.encodeBigInteger(cs1, 512)
);
ResponseAPDU responseAPDU = cm.transmit(cmd);
Assertions.assertNotNull(responseAPDU);
Assertions.assertEquals(ISO7816.SW_NO_ERROR & 0xffff, responseAPDU.getSW());
}

public void sign3beforeDivide(BigInteger cs1) throws Exception {
CommandAPDU cmd = new CommandAPDU(
Consts.CLA_JC2PECDSA,
Consts.INS_SIGN3_BEFORE_DIVIDE,
0,
0,
ProtocolManager.encodeBigInteger(cs1, 512)
);
ResponseAPDU responseAPDU = cm.transmit(cmd);
Assertions.assertNotNull(responseAPDU);
Assertions.assertEquals(ISO7816.SW_NO_ERROR & 0xffff, responseAPDU.getSW());
}

public void sign3divide(BigInteger cs1) throws Exception {
CommandAPDU cmd = new CommandAPDU(
Consts.CLA_JC2PECDSA,
Consts.INS_SIGN3_DIVIDE,
0,
0,
ProtocolManager.encodeBigInteger(cs1, 512)
);
ResponseAPDU responseAPDU = cm.transmit(cmd);
Assertions.assertNotNull(responseAPDU);
Assertions.assertEquals(ISO7816.SW_NO_ERROR & 0xffff, responseAPDU.getSW());
}

public static BigInteger hash(byte[] message) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] h = digest.digest(message);
Expand Down

0 comments on commit d093fd3

Please sign in to comment.