Skip to content

Commit

Permalink
Add deterministic nonce derivation
Browse files Browse the repository at this point in the history
  • Loading branch information
dufkan committed Jul 4, 2021
1 parent 9768b4c commit f377923
Showing 1 changed file with 42 additions and 18 deletions.
60 changes: 42 additions & 18 deletions applet/src/main/java/applet/MainApplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import javacard.security.RandomData;
import applet.jcmathlib.*;

public class MainApplet extends Applet implements MultiSelectable
{
public class MainApplet extends Applet implements MultiSelectable {
public static final byte[] TRANSFORM_C = {
(byte) 0x70, (byte) 0xd9, (byte) 0x12, (byte) 0x0b,
(byte) 0x9f, (byte) 0x5f, (byte) 0xf9, (byte) 0x44,
Expand All @@ -33,10 +32,12 @@ public class MainApplet extends Applet implements MultiSelectable
public ECCurve curve = new ECCurve(true, Wei25519.p, Wei25519.a, Wei25519.b, Wei25519.G, Wei25519.r, Wei25519.k);
public Bignat curveOrder = new Bignat((short) 32, JCSystem.MEMORY_TYPE_PERSISTENT, ecc.bnh);

private byte[] masterKey = new byte[32];
private byte[] prefix = new byte[32];
public Bignat privateKey = new Bignat((short) 32, JCSystem.MEMORY_TYPE_PERSISTENT, ecc.bnh);
public ECPoint publicKey = new ECPoint(curve, ecc.ech);

public Bignat privateNonce = new Bignat((short) 32, JCSystem.MEMORY_TYPE_PERSISTENT, ecc.bnh);
public Bignat privateNonce = new Bignat((short) 64, JCSystem.MEMORY_TYPE_PERSISTENT, ecc.bnh);
public ECPoint publicNonce = new ECPoint(curve, ecc.ech);

public Bignat signature = new Bignat((short) 64, JCSystem.MEMORY_TYPE_PERSISTENT, ecc.bnh);
Expand All @@ -51,13 +52,11 @@ public class MainApplet extends Applet implements MultiSelectable
private byte[] ramArray = JCSystem.makeTransientByteArray(Wei25519.POINT_SIZE, JCSystem.CLEAR_ON_DESELECT);
private RandomData random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);

public static void install(byte[] bArray, short bOffset, byte bLength)
{
public static void install(byte[] bArray, short bOffset, byte bLength) {
new MainApplet(bArray, bOffset, bLength);
}

public MainApplet(byte[] buffer, short offset, byte length)
{

public MainApplet(byte[] buffer, short offset, byte length) {
ecc.bnh.bIsSimulator = true;

curveOrder.from_byte_array(Wei25519.r);
Expand All @@ -67,14 +66,13 @@ public MainApplet(byte[] buffer, short offset, byte length)
register();
}

public void process(APDU apdu)
{
public void process(APDU apdu) {
if (selectingApplet()) // ignore selection command
return;

try {
if(apdu.getBuffer()[ISO7816.OFFSET_CLA] == Consts.CLA_ED25519) {
switch(apdu.getBuffer()[ISO7816.OFFSET_INS]) {
if (apdu.getBuffer()[ISO7816.OFFSET_CLA] == Consts.CLA_ED25519) {
switch (apdu.getBuffer()[ISO7816.OFFSET_INS]) {
case Consts.INS_KEYGEN:
generateKeypair(apdu);
break;
Expand Down Expand Up @@ -124,7 +122,15 @@ public void deselect(boolean b) {}
private void generateKeypair(APDU apdu) {
byte[] apduBuffer = apdu.getBuffer();

random.generateData(ramArray, (short) 0, (short) 32);
random.generateData(masterKey, (short) 0, (short) 32);
hasher.reset();
hasher.doFinal(masterKey, (short) 0, (short) 32, ramArray, (short) 0);
ramArray[0] &= (byte) 0xf8; // Clear lowest three bits
ramArray[31] &= (byte) 0x7f; // Clear highest bit
ramArray[31] |= (byte) 0x40; // Set second-highest bit
changeEndianity(ramArray, (short) 0, (short) 32);

Util.arrayCopyNonAtomic(ramArray, (short) 32, prefix, (short) 0, (short) 32);

privateKey.from_byte_array((short) 32, (short) 0, ramArray, (short) 0);
publicKey.setW(curve.G, (short) 0, curve.POINT_SIZE);
Expand All @@ -138,8 +144,8 @@ private void sign(APDU apdu) {
byte[] apduBuffer = apdu.getBuffer();

// Generate nonce R
random.generateData(ramArray, (short) 0, (short) 32);
privateNonce.from_byte_array((short) 32, (short) 0, ramArray, (short) 0);
deterministicNonce(apduBuffer, ISO7816.OFFSET_CDATA, (short) 32);
// randomNonce();
publicNonce.setW(Wei25519.G, (short) 0, Wei25519.POINT_SIZE);
publicNonce.multiplication(privateNonce);

Expand All @@ -151,6 +157,7 @@ private void sign(APDU apdu) {
hasher.update(ramArray, (short) 0, curve.COORD_SIZE); // A
hasher.doFinal(apduBuffer, ISO7816.OFFSET_CDATA, (short) 32, ramArray, (short) 0); // m
changeEndianity(ramArray, (short) 0, (short) 64);
signature.set_size((short) 64);
signature.from_byte_array((short) 64, (short) 0, ramArray, (short) 0);
signature.mod(curveOrder);
signature.shrink();
Expand All @@ -161,7 +168,7 @@ private void sign(APDU apdu) {

// Return signature (R, s)
encodeEd25519(publicNonce, apduBuffer, (short) 0);
signature.copy_to_buffer(apduBuffer, curve.COORD_SIZE);
signature.prepend_zeros(curve.COORD_SIZE, apduBuffer, curve.COORD_SIZE);
changeEndianity(apduBuffer, curve.COORD_SIZE, curve.COORD_SIZE);

apdu.setOutgoingAndSend((short) 0, (short) (curve.COORD_SIZE + curve.COORD_SIZE));
Expand All @@ -188,18 +195,35 @@ private void encodeEd25519(ECPoint point, byte[] buffer, short offset) {
transformY.mod_add(Bignat_Helper.ONE, curve.pBN);
transformY.mod_inv(curve.pBN);
transformX.mod_mult(transformX, transformY, curve.pBN);
transformX.copy_to_buffer(buffer, offset);
transformX.prepend_zeros(curve.COORD_SIZE, buffer, offset);

buffer[offset] |= x_bit ? (byte) 0x80 : (byte) 0x00;

changeEndianity(buffer, offset, (short) 32);
}

private void changeEndianity(byte[] array, short offset, short len) {
for(short i = 0; i < (short) (len / 2); ++i) {
for (short i = 0; i < (short) (len / 2); ++i) {
byte tmp = array[(short) (offset + len - i - 1)];
array[(short) (offset + len - i - 1)] = array[(short) (offset + i)];
array[(short) (offset + i)] = tmp;
}
}

private void deterministicNonce(byte[] msg, short offset, short len) {
hasher.reset();
hasher.update(prefix, (short) 0, (short) 32);
hasher.doFinal(msg, offset, len, ramArray, (short) 0);
changeEndianity(ramArray, (short) 0, (short) 64);
privateNonce.set_size((short) 64);
privateNonce.from_byte_array((short) 64, (short) 0, ramArray, (short) 0);
privateNonce.mod(curveOrder);
privateNonce.shrink();
}

private void randomNonce() {
random.generateData(ramArray, (short) 0,(short) 32);
privateNonce.set_size((short) 32);
privateNonce.from_byte_array((short) 32, (short) 0, ramArray, (short) 0);
}
}

0 comments on commit f377923

Please sign in to comment.