我是JCard编程的初学者(有2天的经验……),我试图在CREF模拟卡上部署应用程序,该卡生成RSA KeyPair并将公钥发送到主机RMI客户端应用程序,从客户端应用程序启动init方法,我得到此异常:
Exception in thread "main" java.lang.UnsatisfiedLinkError:
com.sun.javacard.impl.NativeMethods.getCurrentContext()B
at com.sun.javacard.impl.NativeMethods.getCurrentContext(Native Method)
at com.sun.javacard.impl.PrivAccess.getCurrentAppID(PrivAccess.java:454)
at javacard.framework.CardRuntimeException.<init>(CardRuntimeException.java:46)
at javacard.security.CryptoException.<init>(DashoA10*..:25)
at com.sun.javacard.javax.smartcard.rmiclient.CardObjectFactory.throwIt(Unknown Source)
at com.sun.javacard.javax.smartcard.rmiclient.CardObjectFactory.throwException(Unknown Source)
at com.sun.javacard.javax.smartcard.rmiclient.CardObjectFactory.getObject(Unknown Source)
at com.sun.javacard.rmiclientlib.JCRemoteRefImpl.parseAPDU(Unknown Source)
at com.sun.javacard.rmiclientlib.JCRemoteRefImpl.invoke(Unknown Source)
at sid2.CompteurImpl_Stub.initialiser(Unknown Source)
at sid2.ClientRmi.main(ClientRmi.java:36)
这是我的JCard小程序中的代码被调用:
package sid2;
import java.rmi.RemoteException;
import javacard.framework.UserException;
import javacard.framework.service.CardRemoteObject;
import javacard.security.*;
import javacardx.crypto.Cipher;
public class CompteurImpl extends CardRemoteObject implements ICompteur {
private byte compteur = 120;
RSAPrivateKey rsa_PrivateKey;
RSAPublicKey rsa_PublicKey;
KeyPair rsa_KeyPair;
Cipher cipherRSA;
public void setPub(byte[] expo, byte[] mod) {
rsa_PublicKey.setExponent(expo, (short) 0, (short) expo.length);
rsa_PublicKey.setModulus(mod, (short) 0, (short) mod.length);
}
public byte[] getPub() {
byte[] ret = null;
rsa_PublicKey.getModulus(ret, (short) 0);
rsa_PublicKey.getExponent(ret, (short) (ret.length + 1));
return ret;
}
public void initialiser(byte v) throws RemoteException, UserException {
rsa_KeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048);
rsa_KeyPair.genKeyPair();
rsa_PublicKey = (RSAPublicKey) rsa_KeyPair.getPublic();
rsa_PrivateKey = (RSAPrivateKey) rsa_KeyPair.getPrivate();
compteur = v;
}
}
谁能指出我在这里做错了什么?
PS:我已经尝试了基本的东西,并且效果很好,例如在Jcard上有一个变量并对其进行递增,获取和设置。
最佳答案
根据JCDK User's Guide (for JC 2.2.2),CREF(C语言RE)实现支持以下算法:
112、128、160、192位ECC
512位RSA
因此,线
rsa_KeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048);
在CREF中执行时应抛出
CryptoException.NO_SUCH_ALGORITHM
(因为CREF不支持2048位RSA)。除了该错误,这很可能是导致异常的原因,您的代码至少还有一个问题:
byte[] ret = null;
rsa_PublicKey.getModulus(ret, (short) 0);
rsa_PublicKey.getExponent(ret, (short) (ret.length + 1));
在这里,您将缓冲区
ret
初始化为null
,但是随后尝试将模数和指数填充到缓冲区中。这两个方法(getModulus()
和getExponent()
)不会为您创建该缓冲区。相反,您需要首先创建适当大小的缓冲区:byte[] buffer = new byte[expected_length]; // Note that you certainly do not want to allocate that buffer within your getPub method!
然后可以将模数和指数填充到该缓冲区中:
byte modLen = rsa_PublicKey.getModulus(buffer, (short) 0);
byte expLen = rsa_PublicKey.getExponent(buffer, (short) modLen);