[英]ECDSA Signature in Javacard
我正在Javacard中使用ECDSA實現簽名代碼。
我的代碼在異常部分輸出0x0003(NO_SUCH_ALGORITHM),這意味着該卡不支持該算法。 我不明白,因為我的供應商告訴我它支持ECC。 我總結說我不知道如何與ECDSA簽約,我想知道。
這是我的完整源代碼
package MyECDSA;
import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.*;
public class MyECDSA extends Applet{
private byte[] PLAINTEXT ;
private ECPrivateKey objECDSAPriKey=null; // Object for ECDSA Private Key
private ECPublicKey objECDSAPubKey=null; // Object for ECDSA Public Key
private KeyPair objECDSAKeyPair=null; // Object for ECDSA Key Pair
private Signature objECDSASign=null; // Object for ECDSA Signature
final static short BAS = 0;
public static void install(byte[] bArray, short bOffset, byte bLength){
new MyECDSA(bArray, bOffset, bLength);
}
private MyECDSA(byte bArray[], short bOffset, byte bLength){
PLAINTEXT = new byte[0x100] ; // Data file
Util.arrayFillNonAtomic(PLAINTEXT, BAS, (short)0x100, (byte)0);
register();
}
//======================================================================================
public void process(APDU apdu){
byte buf[] = apdu.getBuffer();
switch(buf[1])
{
//--------------------------------------------------------
case (byte)0xA4: break;
case (byte)0x46:
// Create ECDSA Keys and Pair
try {
// <<<<<<<<<<<<<<<< Here is the problem >>>>>>>>>>>>>>>>>
objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
//objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_F2M, KeyBuilder.LENGTH_EC_F2M_193);
}
catch(CryptoException c)
{
short reason = c.getReason();
ISOException.throwIt(reason);
}
ISOException.throwIt((short)0x9999); // for check
// Generate Key pair
objECDSAKeyPair.genKeyPair();
// Create Signature Object
objECDSASign = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
objECDSAPriKey = (ECPrivateKey)objECDSAKeyPair.getPrivate();
objECDSAPubKey = (ECPublicKey)objECDSAKeyPair.getPublic();
break;
case (byte)0x2E:
short Le = apdu.setOutgoing();
short sSignLen=0 ;
// Init with Private Key
objECDSASign.init(objECDSAPriKey, Signature.MODE_SIGN);
// Sign Data
sSignLen = objECDSASign.sign(PLAINTEXT, BAS, Le, buf, BAS);
apdu.setOutgoingLength(sSignLen);
apdu.sendBytes(BAS, sSignLen);
break;
//--------------------------------------------------------
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
return;
}
}
和APDU命令如下
[ Card ] <== 00A4040007D4106509900090
[ Card ] ==> 9000
[ Card ] <== 0046000000
[ Card ] ==> 0003
我的開發環境如下。
我已經更改了我的代碼來設置域參數。 但是卡仍然輸出相同的結果(0x0003)。 這是我的完整源代碼。
package MyECDSA;
import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.*;
public class MyECDSA extends Applet{
private byte[] PLAINTEXT ;
private ECPrivateKey objECDSAPriKey=null; // Object for ECDSA Private Key
private ECPublicKey objECDSAPubKey=null; // Object for ECDSA Public Key
private KeyPair objECDSAKeyPair=null; // Object for ECDSA Key Pair
private Signature objECDSASign=null; // Object for ECDSA Signature
final static short BAS = 0;
final static byte[] SecP192r1_P = { // 24
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFE,(byte)0xFF,(byte)0xFF,(byte)0xFF,(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[] SecP192r1_A = { // 24
(byte)0xFC,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFE,(byte)0xFF,(byte)0xFF,(byte)0xFF,(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[] SecP192r1_B = { // 24
(byte)0xB1,(byte)0xB9,(byte)0x46,(byte)0xC1,(byte)0xEC,(byte)0xDE,(byte)0xB8,(byte)0xFE,
(byte)0x49,(byte)0x30,(byte)0x24,(byte)0x72,(byte)0xAB,(byte)0xE9,(byte)0xA7,(byte)0x0F,
(byte)0xE7,(byte)0x80,(byte)0x9C,(byte)0xE5,(byte)0x19,(byte)0x05,(byte)0x21,(byte)0x64};
final static byte[] SecP192r1_S = { // 20
(byte)0xD5,(byte)0x96,(byte)0x21,(byte)0xE1,(byte)0xEA,(byte)0x20,(byte)0x81,(byte)0xD3,
(byte)0x28,(byte)0x95,(byte)0x57,(byte)0xED,(byte)0x64,(byte)0x2F,(byte)0x42,(byte)0xC8,
(byte)0x6F,(byte)0xAE,(byte)0x45,(byte)0x30};
final static byte[] SecP192r1_G = { // 25
(byte)0x12,(byte)0x10,(byte)0xFF,(byte)0x82,(byte)0xFD,(byte)0x0A,(byte)0xFF,(byte)0xF4,
(byte)0x00,(byte)0x88,(byte)0xA1,(byte)0x43,(byte)0xEB,(byte)0x20,(byte)0xBF,(byte)0x7C,
(byte)0xF6,(byte)0x90,(byte)0x30,(byte)0xB0,(byte)0x0E,(byte)0xA8,(byte)0x8D,(byte)0x18,(byte)0x03};
final static byte[] SecP192r1_N = { // 24
(byte)0x31,(byte)0x28,(byte)0xD2,(byte)0xB4,(byte)0xB1,(byte)0xC9,(byte)0x6B,(byte)0x14,
(byte)0x36,(byte)0xF8,(byte)0xDE,(byte)0x99,(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 short SecP192r1_H = 1;
//======================================================================================
public static void install(byte[] bArray, short bOffset, byte bLength){
new MyECDSA(bArray, bOffset, bLength);
}
private MyECDSA(byte bArray[], short bOffset, byte bLength){
PLAINTEXT = new byte[0x100] ; // Data file
Util.arrayFillNonAtomic(PLAINTEXT, BAS, (short)0x100, (byte)0);
register();
}
//======================================================================================
public void process(APDU apdu){
byte buf[] = apdu.getBuffer();
switch(buf[1])
{
//--------------------------------------------------------
case (byte)0xA4: break;
case (byte)0x46:
// Create ECDSA Keys and Pair
try {
// <<<<<<<<<<<<<<<< Here is the problem >>>>>>>>>>>>>>>>>
objECDSAPriKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_192, false);
ISOException.throwIt((short)0x8888); // for check
objECDSAPubKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_192, false);
// set EC Domain Parameters
objECDSAPubKey.setFieldFP(SecP192r1_P, BAS, (short)24);
objECDSAPubKey.setA(SecP192r1_A, BAS, (short)24);
objECDSAPubKey.setB(SecP192r1_B, BAS, (short)24);
objECDSAPubKey.setG(SecP192r1_G, BAS, (short)25);
objECDSAPubKey.setK(SecP192r1_H);
objECDSAPubKey.setR(SecP192r1_N, BAS, (short)24);
objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
}
catch(CryptoException c)
{
short reason = c.getReason();
ISOException.throwIt(reason); // for check
}
// On-Card Key Generation Process
objECDSAKeyPair.genKeyPair();
// Obtain Key References
objECDSAPriKey = (ECPrivateKey)objECDSAKeyPair.getPrivate();
objECDSAPubKey = (ECPublicKey)objECDSAKeyPair.getPublic();
// Create Signature Object
objECDSASign = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
break;
case (byte)0x2E:
short Le = apdu.setOutgoing();
short sSignLen=0 ;
// Init with Private Key
objECDSASign.init(objECDSAPriKey, Signature.MODE_SIGN);
// Sign Data
sSignLen = objECDSASign.sign(PLAINTEXT, BAS, Le, buf, BAS);
apdu.setOutgoingLength(sSignLen);
apdu.sendBytes(BAS, sSignLen);
break;
//--------------------------------------------------------
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
return;
}
}
Java Card中沒有默認的EC域參數。 需要使用ECPublicKey
設置域參數的ECPublicKey
和ECPrivateKey
創建KeyPair
(因此點W和秘密S可以保持為空)。 之后,可以調用genKeyPair()
,至少如果該卡支持F(2m)或F(p)橢圓曲線加密以及指定的密鑰大小。
添加
請注意,NXP JCOP芯片可能需要為公鑰和私鑰設置這些參數。 參數應具有鍵大小(對於單獨的值)或未壓縮的橢圓曲線點。 問題中G的值似乎是一個壓縮點。 只有輔助因子(對於setH
)應該只有值1。
注意,只有具有非對稱協處理器的芯片可以支持橢圓曲線; 並非所有卡都是平等創建/配置的。 請聯系您的供應商了解詳情
如果嘗試創建特定算法的實例(在您的情況下為KeyPair.ALG_EC_FP&KeyBuilder.LENGTH_EC_FP_192)失敗並且NO_SUCH_ALGORITHM,則您的卡完全不支持(例如,舊硬件)或禁用它。
Project JCAlgTester允許您獲取特定卡支持的算法的完整列表。 也可以使用多個不同卡的結果數據庫(但最好通過上傳JCAlgTester小程序直接檢查您的特定卡)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.