From d093fd3b876653515c97422b88d279e4c29aabe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=C3=ADn=20Dufka?= Date: Mon, 8 Jul 2024 10:36:52 +0200 Subject: [PATCH] add partial sign3 profiling --- applet/src/main/java/jc2pecdsa/Consts.java | 5 ++ applet/src/main/java/jc2pecdsa/JC2pECDSA.java | 46 ++++++++++ applet/src/test/java/tests/AppletTest.java | 89 ++++++++++++++++++- .../src/test/java/tests/ProtocolManager.java | 53 +++++++++++ 4 files changed, 192 insertions(+), 1 deletion(-) diff --git a/applet/src/main/java/jc2pecdsa/Consts.java b/applet/src/main/java/jc2pecdsa/Consts.java index 8f9af3f..32e3d38 100644 --- a/applet/src/main/java/jc2pecdsa/Consts.java +++ b/applet/src/main/java/jc2pecdsa/Consts.java @@ -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; diff --git a/applet/src/main/java/jc2pecdsa/JC2pECDSA.java b/applet/src/main/java/jc2pecdsa/JC2pECDSA.java index 5fa6b6c..3770e2d 100755 --- a/applet/src/main/java/jc2pecdsa/JC2pECDSA.java +++ b/applet/src/main/java/jc2pecdsa/JC2pECDSA.java @@ -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); } @@ -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); @@ -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()); diff --git a/applet/src/test/java/tests/AppletTest.java b/applet/src/test/java/tests/AppletTest.java index b8a2e6d..f67a7c6 100755 --- a/applet/src/test/java/tests/AppletTest.java +++ b/applet/src/test/java/tests/AppletTest.java @@ -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()); @@ -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(); + } } \ No newline at end of file diff --git a/applet/src/test/java/tests/ProtocolManager.java b/applet/src/test/java/tests/ProtocolManager.java index 488dba1..7b95bb5 100644 --- a/applet/src/test/java/tests/ProtocolManager.java +++ b/applet/src/test/java/tests/ProtocolManager.java @@ -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);