JavaCard 3.2生成EC密钥对异常及签名验证失败求助
Oracle JavaCard 3.2模拟器EC密钥对生成与验证问题
我正在使用Oracle JavaCard模拟器最新版本3.2,在生成EC密钥对并导出公钥时遇到异常,同时签名验证环节抛出加密异常。
1. 初始代码与异常公钥输出
尝试生成P-256(secp256r1)EC密钥对并通过ECPublicKey.getW()导出公钥,代码如下:
// Create ECC key pair (P-256 / secp256r1) KeyPair eccKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); eccKeyPair.genKeyPair(); ECPublicKey eccPublicKey = (ECPublicKey)eccKeyPair.getPublic(); short wLength = eccPublicKey.getW(buffer, (short)2); apdu.setOutgoing(); apdu.setOutgoingLength((short)(2 + wLength)); buffer[0] = (byte)((wLength >> 8) & 0xFF); buffer[1] = (byte)(wLength & 0xFF); apdu.sendBytes((short) 0, (short)(2 + wLength));
得到的输出为00210424603E79077F33047A46079DABB6155E0F9A46B70D570E52B61831AFB9AAAAF4,公钥长度为33字节。33字节是压缩EC公钥的有效长度,但前缀应为02或03,而非04——04是非压缩公钥的前缀,对应长度应为65字节。
2. 设置曲线参数后的尝试
了解到生成密钥对前需设置EC公私钥参数,于是修改代码如下:
ECPrivateKey eccPrivateKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false /* keyEncryption */); setCurveParameters(eccPrivateKey); // Set SecP256r1 parameters ECPublicKey eccPublicKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false /* keyEncryption */); setCurveParameters(eccPublicKey); // Set SecP256r1 parameters KeyPair eccKeyPair = new KeyPair(eccPublicKey, eccPrivateKey); eccKeyPair.genKeyPair(); short wLength = eccPublicKey.getW(buffer, (short)2);
结果仍类似:002104B792239DBD35FC129592F258E8231232B30D2FA8907E984788290BC0B7100049,问题未解决。
3. 签名验证时的加密异常
忽略公钥异常进行签名测试,代码如下:
try { ECPrivateKey eccPrivateKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false /* keyEncryption */); setCurveParameters(eccPrivateKey); ECPublicKey eccPublicKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false /* keyEncryption */); setCurveParameters(eccPublicKey); KeyPair eccKeyPair = new KeyPair(eccPublicKey, eccPrivateKey); eccKeyPair.genKeyPair(); byte[] messageBytes = new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B}; Signature eccSignature = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false); eccSignature.init(eccPrivateKey, Signature.MODE_SIGN); short signatureLength = eccSignature.sign( messageBytes, (short)0, (short)messageBytes.length, // input buffer, (short)0 // output (reuse buffer) ); Signature eccVerificationSignature = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false); eccVerificationSignature.init(eccPublicKey, Signature.MODE_VERIFY); // <<<<<<<<< CryptoException here: 'javacard.security.CryptoException (reason=0x0001)' - EC_POINT not created: error:08000066:elliptic curve routines::invalid encoding apdu.setOutgoing(); apdu.setOutgoingLength(signatureLength); apdu.sendBytes((short) 0, signatureLength); } catch (CryptoException e) { ISOException.throwIt((short)0x6F01); }
调用eccSignature.init(eccPublicKey, Signature.MODE_VERIFY);时抛出异常:javacard.security.CryptoException (reason=0x0001)。
Oracle JavaCard模拟器日志如下:
SEVERE |msg|000598|grp:hal | EC_POINT not created: error:08000066:elliptic curve routines::invalid encoding WARNING|msg|000599|grp:jcre| Exception: WARNING|msg|000599|grp:jcre| javacard.security.CryptoException (reason=0x0001) WARNING|msg|000599|grp:jcre| at javacard.security.CryptoException.throwIt_S (pc=@0x63c02b92) WARNING|msg|000599|grp:jcre| at javacard.security.<anonymous> (pc=@0x63c035ee) WARNING|msg|000599|grp:jcre| at <unknown> (pc=@0x63c2b09b) WARNING|msg|000599|grp:jcre| at <unknown> (pc=@(nil)) WARNING|msg|000600|grp:jcre| Exception: WARNING|msg|000600|grp:jcre| javacard.framework.ISOException (reason=0x6F01) WARNING|msg|000600|grp:jcre| at javacard.framework.ISOException.throwIt_S (pc=@0x63c00e5e) WARNING|msg|000600|grp:jcre| at <unknown> (pc=@0x63c2b0b7) WARNING|msg|000600|grp:jcre| at <unknown> (pc=@(nil))
日志证实EC密钥对未正确初始化。
4. setCurveParameters方法定义
以下是设置SecP256r1曲线参数的代码:
private final static byte[] p = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 }; private final static byte[] a = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 }; private final static byte[] b = { 0x5a, (byte) 0xc6, 0x35, (byte) 0xd8, (byte) 0xaa, 0x3a, (byte) 0x93, (byte) 0xe7, (byte) 0xb3, (byte) 0xeb, (byte) 0xbd, 0x55, 0x76, (byte) 0x98, (byte) 0x86, (byte) 0xbc, 0x65, 0x1d, 0x06, (byte) 0xb0, (byte) 0xcc, 0x53, (byte) 0xb0, (byte) 0xf6, 0x3b, (byte) 0xce, 0x3c, 0x3e, 0x27, (byte) 0xd2, 0x60, 0x4b }; private final static byte[] G = { 0x04, 0x6b, 0x17, (byte) 0xd1, (byte) 0xf2, (byte) 0xe1, 0x2c, 0x42, 0x47, (byte) 0xf8, (byte) 0xbc, (byte) 0xe6, (byte) 0xe5, 0x63, (byte) 0xa4, 0x40, (byte) 0xf2, 0x77, 0x03, 0x7d, (byte) 0x81, 0x2d, (byte) 0xeb, 0x33, (byte) 0xa0, (byte) 0xf4, (byte) 0xa1, 0x39, 0x45, (byte) 0xd8, (byte) 0x98, (byte) 0xc2, (byte) 0x96, 0x4f, (byte) 0xe3, 0x42, (byte) 0xe2, (byte) 0xfe, 0x1a, 0x7f, (byte) 0x9b, (byte) 0x8e, (byte) 0xe7, (byte) 0xeb, 0x4a, 0x7c, 0x0f, (byte) 0x9e, 0x16, 0x2b, (byte) 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, (byte) 0xce, (byte) 0xcb, (byte) 0xb6, 0x40, 0x68, 0x37, (byte) 0xbf, 0x51, (byte) 0xf5 }; private final static byte[] r = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 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, 0x17, (byte) 0x9e, (byte) 0x84, (byte) 0xf3, (byte) 0xb9, (byte) 0xca, (byte) 0xc2, (byte) 0xfc, 0x63, 0x25, 0x51 }; private final static byte k = 0x01; public static void setCurveParameters(ECKey key) { key.setFieldFP(p, (short) 0, (short) p.length); key.setA(a, (short) 0, (short) a.length); key.setB(b, (short) 0, (short) b.length); key.setG(G, (short) 0, (short) G.length); key.setR(r, (short) 0, (short) r.length); key.setK(k); }
内容的提问来源于stack exchange,提问作者OlivierM
相关产品推荐
相关产品推荐

