我是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);

09-27 18:25