I use ECDSA_SHA256 with sec256p-r1 domain parameter to sign, verify => Verify is OK
But the result is invalid.
I don't know why.
Code: Select all
/**
*
*/
package ECDSAproject;
import javacard.framework.*;
import javacard.security.CryptoException;
import javacard.security.ECKey;
import javacard.security.ECPrivateKey;
import javacard.security.ECPublicKey;
import javacard.security.KeyBuilder;
import javacard.security.KeyPair;
import javacard.security.MessageDigest;
import javacard.security.RandomData;
import javacard.security.Signature;
import javacardx.annotations.*;
import javacardx.crypto.Cipher;
/**
* Applet class
*
* @author <user>
*/
@StringPool(value = {
@StringDef(name = "Package", value = "ECDSAproject"),
@StringDef(name = "AppletName", value = "ECDSAapplet")},
// Insert your strings here
name = "ECDSAappletStrings")
public class ECDSAapplet extends Applet {
final static byte[] SecP256r1_P = {
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
final static byte[] SecP256r1_A = {
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFC};
final static byte[] SecP256r1_B = {
(byte)0x5A,(byte)0xC6,(byte)0x35,(byte)0xD8,(byte)0xAA,(byte)0x3A,(byte)0x93,(byte)0xE7,
(byte)0xB3,(byte)0xEB,(byte)0xBD,(byte)0x55,(byte)0x76,(byte)0x98,(byte)0x86,(byte)0xBC,
(byte)0x65,(byte)0x1D,(byte)0x06,(byte)0xB0,(byte)0xCC,(byte)0x53,(byte)0xB0,(byte)0xF6,
(byte)0x3B,(byte)0xCE,(byte)0x3C,(byte)0x3E,(byte)0x27,(byte)0xD2,(byte)0x60,(byte)0x4B};
final static byte[] SecP256r1_S = {
(byte)0xC4,(byte)0x9D,(byte)0x36,(byte)0x08,(byte)0x86,(byte)0xE7,(byte)0x04,(byte)0x93,
(byte)0x6A,(byte)0x66,(byte)0x78,(byte)0xE1,(byte)0x13,(byte)0x9D,(byte)0x26,(byte)0xB7,
(byte)0x81,(byte)0x9F,(byte)0x7E,(byte)0x90};
// Uncompress form
final static byte[] SecP256r1_G = {
(byte)0x04,(byte)0x6B,(byte)0x17,(byte)0xD1,(byte)0xF2,(byte)0xE1,(byte)0x2C,(byte)0x42,(byte)0x47,
(byte)0xF8,(byte)0xBC,(byte)0xE6,(byte)0xE5,(byte)0x63,(byte)0xA4,(byte)0x40,(byte)0xF2,
(byte)0x77,(byte)0x03,(byte)0x7D,(byte)0x81,(byte)0x2D,(byte)0xEB,(byte)0x33,(byte)0xA0,
(byte)0xF4,(byte)0xA1,(byte)0x39,(byte)0x45,(byte)0xD8,(byte)0x98,(byte)0xC2,(byte)0x96,
(byte)0x4F,(byte)0xE3,(byte)0x42,(byte)0xE2,(byte)0xFE,(byte)0x1A,(byte)0x7F,(byte)0x9B,
(byte)0x8E,(byte)0xE7,(byte)0xEB,(byte)0x4A,(byte)0x7C,(byte)0x0F,(byte)0x9E,(byte)0x16,
(byte)0x2B,(byte)0xCE,(byte)0x33,(byte)0x57,(byte)0x6B,(byte)0x31,(byte)0x5E,(byte)0xCE,
(byte)0xCB,(byte)0xB6,(byte)0x40,(byte)0x68,(byte)0x37,(byte)0xBF,(byte)0x51,(byte)0xF5};
final static byte[] SecP256r1_N = {
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xBC,(byte)0xE6,(byte)0xFA,(byte)0xAD,(byte)0xA7,(byte)0x17,(byte)0x9E,(byte)0x84,
(byte)0xF3,(byte)0xB9,(byte)0xCA,(byte)0xC2,(byte)0xFC,(byte)0x63,(byte)0x25,(byte)0x51};
final static short SecP256r1_H = 1;
private byte[] PLAINTEXT;
private ECPrivateKey objECDSAPriKey = null;
private ECPublicKey objECDSAPubKey = null;
private KeyPair objECDSAKeyPair = null;
private Signature objECDSASign = null;
private ECKey objECKey = null;
private short objECDSAPubKeyLen;
private short objECDSAPriKeyLen;
private byte[] TEMP_ARR;
private static short TEMP_ARR_LEN = (short)256;
private final static byte ECDSA_GEN_KEY_PAIR = (byte)0x46;
private final static byte ECDSA_GET_PUBLIC_KEY = (byte)0x47;
private final static byte ECDSA_GET_PRIVATE_KEY = (byte)0x48;
private final static byte ECDSA_SIGN = (byte)0x49;
private final static byte ECDSA_VERIFY = (byte)0x4A;
private final static byte ECDSA_SET_PRIVATE_KEY = (byte)0x4B;
private final static byte ECDSA_SET_PUBLIC_KEY = (byte)0x4C;
/**
* Installs this applet.
*
* @param bArray
* the array containing installation parameters
* @param bOffset
* the starting offset in bArray
* @param bLength
* the length in bytes of the parameter data in bArray
*/
public static void install(byte[] bArray, short bOffset, byte bLength) {
new ECDSAapplet().register();
}
/**
* Only this class's install method should create the applet object.
*/
public ECDSAapplet() {
PLAINTEXT = JCSystem.makeTransientByteArray((short)0x100, JCSystem.CLEAR_ON_DESELECT);
TEMP_ARR = JCSystem.makeTransientByteArray(TEMP_ARR_LEN, JCSystem.CLEAR_ON_DESELECT);
}
/**
* Processes an incoming APDU.
*
* @see APDU
* @param apdu
* the incoming APDU
*/
@Override
public void process(APDU apdu) {
//Insert your code here
byte[] buf = apdu.getBuffer();
// ISOException.throwIt((short)0x9FAA);
if ((buf[ISO7816.OFFSET_CLA] == 0) &&
(buf[ISO7816.OFFSET_INS] == (byte) (0xA4))) {
return;
}
switch(buf[ISO7816.OFFSET_INS]){
case (byte)0xA4:{
ISOException.throwIt((short)0x9FAA);
break;
}
// Generate Key pair
case (byte)ECDSA_GEN_KEY_PAIR:{
apdu.setIncomingAndReceive();
ECDSAGenKeyPair(apdu, buf);
break;
}
// Get Public Key
case (byte)ECDSA_GET_PUBLIC_KEY:{
ECDSAGetPubKey(apdu, buf);
break;
}
// Get Private Key
case (byte)ECDSA_GET_PRIVATE_KEY:{
ECDSAGetPriKey(apdu, buf);
break;
}
// Signature
case (byte)ECDSA_SIGN:{
PLAINTEXT[0] = (byte)0x61;
apdu.setIncomingAndReceive();
ECDSASignature(apdu,buf,buf,ISO7816.OFFSET_CDATA,apdu.getIncomingLength());
break;
}
// Verify
case (byte)ECDSA_VERIFY:{
PLAINTEXT[0] = (byte)0x61;
apdu.setIncomingAndReceive();
short DataLen = buf[ISO7816.OFFSET_LC];
ECDSAVerify(apdu,buf,buf,(short)(ISO7816.OFFSET_CDATA + apdu.getIncomingLength() - 1),(short)1);
break;
}
// Set Private key
case ECDSA_SET_PRIVATE_KEY:{
apdu.setIncomingAndReceive();
ECDSASetPrivKey(buf);
break;
}
// Set Public key
case ECDSA_SET_PUBLIC_KEY:{
apdu.setIncomingAndReceive();
ECDSASetPubKey(buf);
break;
}
default :{
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
break;
}
}
}
private void ECDSAGenKeyPair(APDU apdu,byte[] buf){
try{
if (objECDSAPriKey != null){
objECDSAPriKey.clearKey();
objECDSAPubKey.clearKey();
}
objECDSAPriKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false);
objECDSAPubKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false);
objECDSASign = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false);
objECDSASign = Signature.getInstance(MessageDigest.ALG_SHA_256, Signature.SIG_CIPHER_ECDSA, Cipher.PAD_NULL, false);
objECDSAPubKey.setFieldFP(SecP256r1_P, (short)0, (short)SecP256r1_P.length);
objECDSAPubKey.setA(SecP256r1_A, (short)0, (short)ECDSADomainParameter.SecP256r1_A.length);
objECDSAPubKey.setB(SecP256r1_B, (short)0, (short)SecP256r1_B.length);
objECDSAPubKey.setG(SecP256r1_G, (short)0, (short)SecP256r1_G.length);
objECDSAPubKey.setR(SecP256r1_N, (short)0, (short)SecP256r1_N.length);
objECDSAPubKey.setK(SecP256r1_H);
objECDSAPriKey.setFieldFP(SecP256r1_P, (short)0, (short)ECDSADomainParameter.SecP256r1_P.length);
objECDSAPriKey.setA(SecP256r1_A, (short)0, (short)SecP256r1_A.length);
objECDSAPriKey.setB(SecP256r1_B, (short)0, (short)SecP256r1_B.length);
objECDSAPriKey.setG(SecP256r1_G, (short)0, (short)SecP256r1_G.length);
objECDSAPriKey.setR(SecP256r1_N, (short)0, (short)SecP256r1_N.length);
objECDSAPriKey.setK(SecP256r1_H);
objECDSAKeyPair = new KeyPair(objECDSAPubKey,objECDSAPriKey);
objECDSAKeyPair.genKeyPair();
}
catch(CryptoException ex){
short reason = ex.getReason();
ISOException.throwIt(reason);
}
ISOException.throwIt(ISO7816.SW_NO_ERROR);
}
private void ECDSAGetPubKey(APDU apdu,byte[] buf){
try{
objECDSAPubKey = (ECPublicKey)objECDSAKeyPair.getPublic();
objECDSAPubKeyLen = objECDSAPubKey.getW(buf, ISO7816.OFFSET_CDATA);
}
catch(CryptoException ex){
ISOException.throwIt(ex.getReason());
}
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA,objECDSAPubKeyLen);
}
private void ECDSAGetPriKey(APDU apdu,byte[] buf){
try{
objECDSAPriKey = (ECPrivateKey)objECDSAKeyPair.getPrivate();
objECDSAPriKeyLen = objECDSAPriKey.getS(buf, ISO7816.OFFSET_CDATA);
}
catch(CryptoException ex){
ISOException.throwIt(ex.getReason());
}
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA,objECDSAPriKeyLen);
}
private void ECDSAVerify(APDU apdu,byte[] buf,byte[] PlainText,short PlainTextOffset,short PlainTextLen){
short Signlen = buf[ISO7816.OFFSET_LC];
boolean VerifyResult=false;
objECDSASign.init(objECDSAPubKey, Signature.MODE_VERIFY);
VerifyResult = objECDSASign.verify(PlainText,PlainTextOffset, PlainTextLen, buf, ISO7816.OFFSET_CDATA ,Signlen);
if (VerifyResult){
ISOException.throwIt(ISO7816.SW_NO_ERROR);
}
else{
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
}
private void ECDSASignature(APDU apdu,byte[] buf,byte[] PlainText,short PlainTextOffset,short PlainTextLen){
short sSignLen=0;
byte result=0;
try{
objECDSASign.init(objECDSAPriKey, Signature.MODE_SIGN);
sSignLen = objECDSASign.sign(PlainText, PlainTextOffset,PlainTextLen, buf, ISO7816.OFFSET_CDATA);
}
catch(CryptoException ex){
ISOException.throwIt(ex.getReason());
}
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, sSignLen);
}
private void ECDSASetPrivKey(byte[] buf){
objECDSAPriKey.setS(buf, ISO7816.OFFSET_CDATA, buf[ISO7816.OFFSET_LC]);
}
private void ECDSASetPubKey(byte[] buf){
objECDSAPubKey.setW(buf, ISO7816.OFFSET_CDATA, buf[ISO7816.OFFSET_LC]);
}
}