首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用OpenSC智能卡生成签名

用OpenSC智能卡生成签名
EN

Stack Overflow用户
提问于 2022-07-05 12:18:00
回答 1查看 83关注 0票数 0

我有氪星智能卡来签署数据字节,并为它获得签名和证书。

我有java工具可以这样做,在Java 8之前,一切都很好。现在,应用程序迁移到Java 11。问题从这里开始。

  1. SunPKCS11.jar/库不是Java 11的一部分,因此应用程序中断。
  2. 我尝试了不同的解决方案,通过互联网和甲骨文发布说明,它建议使用java.security包的密码操作。

我无法从Java 8切换到java 11,任何支持都是非常有用的。

编辑-1:最低可用代码

  • 签名计算器用于解析签名。
  • 它是用Java 8&SunPKCS11.jar编写的,希望将它迁移到Java 11

“”“

代码语言:javascript
复制
import java.io.IOException;
import java.util.Scanner;

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

import sun.security.pkcs11.wrapper.CK_ATTRIBUTE;
import sun.security.pkcs11.wrapper.CK_MECHANISM;
import sun.security.pkcs11.wrapper.CK_RSA_PKCS_PSS_PARAMS;
import sun.security.pkcs11.wrapper.PKCS11;
import sun.security.pkcs11.wrapper.PKCS11Constants;
import sun.security.pkcs11.wrapper.PKCS11Exception;

public class Application {

  public static void main(String[] args) {
    try {
      // PKCS11 middleware (UBK PKI) path
      String libraryPath = "";

      OpenScPkcs11 openScPkcs11 = new OpenScPkcs11(libraryPath);

      openScPkcs11.login("", "");
      byte[] hash = null;
      String keypath = null;
      String oid = null;
      String authbits = null;
      openScPkcs11.calcSign(hash, keypath, oid, authbits);

    }
    catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

}

class OpenScPkcs11 {

  private static HexBinaryAdapter hexBinaryAdapter = new HexBinaryAdapter();

  private int slotId = 0x3;
  private String libraryPath;
  private PKCS11 pkcs11Instance;
  private String signatureAlgo = "RSA";
  private long session = -1;
  private boolean isLoginDone = false;
  private SignatureMechanism.Algorithms algorithm = SignatureMechanism.Algorithms.SHA256;

  public OpenScPkcs11(String libraryPath) throws IOException, PKCS11Exception {
    this.libraryPath = libraryPath;
    initializeMiddleware();
  }


  public void calcSign(byte[] hash, String keyPath, String userOid, String authbits) throws Exception {
    byte[] signature = new byte[512];

    if (this.pkcs11Instance != null) {

      if (this.session < 0) {
        this.openSession();
      }

      if (!this.isLoginDone) {
        this.login("", "");
      }

      Mechanism mechanism = SignatureMechanism.getMechanism(this.algorithm);


      CK_ATTRIBUTE[] pTemplate = new CK_ATTRIBUTE[3];
      pTemplate[0] = new CK_ATTRIBUTE(PKCS11Constants.CKA_CLASS, PKCS11Constants.CKO_PRIVATE_KEY);
      pTemplate[1] = new CK_ATTRIBUTE(PKCS11Constants.CKA_VENDOR_DEFINED + 1, keyPath);
      pTemplate[2] = new CK_ATTRIBUTE(PKCS11Constants.CKA_VENDOR_DEFINED + 2, authbits);

      // define the attibutes for certificate
      CK_ATTRIBUTE[] certAttribute = new CK_ATTRIBUTE[1];
      certAttribute[0] = new CK_ATTRIBUTE(PKCS11Constants.CKA_VENDOR_DEFINED + 3);

      long[] c_FindObjects = null;

      this.pkcs11Instance.C_FindObjectsInit(this.session, pTemplate);
      c_FindObjects = this.pkcs11Instance.C_FindObjects(this.session, 32);
      this.pkcs11Instance.C_FindObjectsFinal(this.session);

      CK_MECHANISM pMechanism = null;

      // RSA Algorithm
      String signatureAlgorithmType = this.getSignatureAlgorithmType();

      if (signatureAlgorithmType.equalsIgnoreCase("RSA")) {
        pMechanism = new CK_MECHANISM(mechanism.getId());

        CK_RSA_PKCS_PSS_PARAMS ck_RSA_PKCS_PSS_PARAMS =
            new CK_RSA_PKCS_PSS_PARAMS(this.algorithm.name(), "MGF1", this.algorithm.name(), (int) mechanism.getsLen());
        pMechanism.pParameter = ck_RSA_PKCS_PSS_PARAMS;
      }
      else if (signatureAlgorithmType.equalsIgnoreCase("ECDSA")) { // ECDSA Algorithm
        pMechanism = new CK_MECHANISM(PKCS11Constants.CKM_ECDSA);
      }
      else {
        throw new Exception("Signature algorithm " + signatureAlgorithmType + " is not supported");
      }

      if ((c_FindObjects != null) && (c_FindObjects.length > 0)) {
        long c_FindObjectFound = c_FindObjects[0];
        boolean objFound = false;

        for (long c_FindObject : c_FindObjects) {
          this.pkcs11Instance.C_GetAttributeValue(this.session, c_FindObject, certAttribute);


          // Binary certificate as byte array
          byte[] certificateBytes = certAttribute[0].getByteArray();

          if ((userOid != null) && !userOid.isEmpty()) {
            // Match certificate with userOid, if matches (Certificate parser used)
            if (parseOidInfo(certificateBytes, userOid)) {
              c_FindObjectFound = c_FindObject;
              objFound = true;
              break;
            }
          }
        }

        if (objFound) {
          System.out.println("Signature found for given OID configuration.");
        }
        else {
          this.pkcs11Instance.C_GetAttributeValue(this.session, c_FindObjectFound, certAttribute);
          CertificateParser certificateParser = new CertificateParser(certAttribute[0].getByteArray());
        }
          this.pkcs11Instance.C_SignInit(this.session, pMechanism, c_FindObjectFound);
          this.pkcs11Instance.C_SignUpdate(this.session, 0, hash, 0, (int) mechanism.getsLen());
          signature = this.pkcs11Instance.C_SignFinal(this.session, mechanism.getSignFinalArgument());
        
      }
      else {
        String errorMessage = "Unable to find keys.";
        throw new Exception(errorMessage);
      }
    }
    else {
      throw new Exception("Initialize middleware first.");
    }
  }


  /**
   * @return
   */
  private String getSignatureAlgorithmType() {
    return this.signatureAlgo;
  }


  public void login(String userName, String password) throws Exception {
    if (this.pkcs11Instance != null) {
      openSession();
      String pwd = password;
      if (pwd == null || pwd.trim().isEmpty()) {
        Scanner sc = new Scanner(System.in);
        pwd = sc.next();
        sc.close();
      }
      this.pkcs11Instance.C_Login(this.session, PKCS11Constants.CKU_USER, pwd.toCharArray());
      this.isLoginDone = true;
    }
    else {
      throw new Exception("Initialize middleware first.");
    }
  }

  public void logout() throws PKCS11Exception {
    if (this.pkcs11Instance != null) {
      this.pkcs11Instance.C_Logout(this.session);
    }
  }


  public void openSession() throws Exception {
    if (this.pkcs11Instance != null) {
      if (this.session < 0) {

        long[] c_GetSlotList = this.pkcs11Instance.C_GetSlotList(true);

        if ((c_GetSlotList != null) && (c_GetSlotList.length > 0)) {
          for (long element : c_GetSlotList) {
            if (element == this.slotId) {
              this.session =
                  this.pkcs11Instance.C_OpenSession(this.slotId, PKCS11Constants.CKF_SERIAL_SESSION, null, null);
              break;
            }
          }
        }
      }
    }
    else {
      throw new Exception("Initialize middleware first.");
    }
  }

  public void closeSession() throws PKCS11Exception {
    if ((this.pkcs11Instance != null) && (this.session >= 0)) {
      this.pkcs11Instance.C_CloseSession(this.session);
      this.session = -1;
    }
  }

  public void initializeMiddleware(String libraryPath1) throws IOException, PKCS11Exception {
    this.pkcs11Instance = PKCS11.getInstance(libraryPath1, "C_GetFunctionList", null, false);
    this.libraryPath = libraryPath1;
  }

  public void initializeMiddleware() throws IOException, PKCS11Exception {
    this.pkcs11Instance = PKCS11.getInstance(this.libraryPath, "C_GetFunctionList", null, false);
  }

  public static String getString(final byte[] data) {
    if ((data != null) && (data.length > 0)) {
      return hexBinaryAdapter.marshal(data);
    }
    return null;
  }
}

class SignatureMechanism {

  public static enum Algorithms {

                                 SHA256(0x250),
                                 /**
                                  * Hash calculation Algorithm
                                  */
                                 RIPEMD160(0x240),
                                 /**
                                  * Hash calculation Algorithm
                                  */
                                 RIPEMD160_1(0x0),

                                 /**
                                  * Secure Hash Algorithm 512 for hash Calculation
                                  */
                                 SHA512(0x251);

    private int value = 0;

    private Algorithms(final int algorithmValue) {
      this.value = algorithmValue;
    }

    /**
     * @return the hash value
     */
    public int getValue() {
      return this.value;
    }
  }

  /**
   * @param algorithm : Algorithm used for hash calculation
   * @return signature mechanism
   */
  public static Mechanism getMechanism(final Algorithms algorithm) {

    Mechanism mechanism = new Mechanism();
    if (algorithm == Algorithms.SHA256) {
      mechanism.setHashAlg(PKCS11Constants.CKM_SHA256);
      mechanism.setMgf(PKCS11Constants.CKG_MGF1_SHA1 + 1);
      mechanism.setsLen(32);
      mechanism.setSignFinalArgument(512);
    } // TODO Verify with ETAS Middleware team
    else if (algorithm == Algorithms.SHA512) {
      mechanism.setHashAlg(PKCS11Constants.CKM_SHA512);
      mechanism.setMgf(PKCS11Constants.CKG_MGF1_SHA1 + 1);
      mechanism.setsLen(64);
      mechanism.setSignFinalArgument(1024);
    }
    else if (algorithm == Algorithms.RIPEMD160) {
      mechanism.setHashAlg(PKCS11Constants.CKM_RIPEMD160);
      mechanism.setMgf(0x80000001); // hard coded becuase it is defined by escrypt and not present in PKCS11
      mechanism.setsLen(20);
    }
    else if (algorithm == Algorithms.RIPEMD160_1) {
      mechanism.setId(PKCS11Constants.CKM_RIPEMD160_RSA_PKCS);
    }

    return mechanism;
  }

}
class Mechanism{

  private long hashAlg;
  private long mgf;
  private long sLen;
  private long ulMaxObjectCount = 32;
  private int signFinalArgument = 128;
  private long id = PKCS11Constants.CKM_RSA_PKCS_PSS;


  /**
   * @return the hashAlg
   */
  public long getHashAlg() {
    return hashAlg;
  }


  /**
   * @param hashAlg the hashAlg to set
   */
  public void setHashAlg(long hashAlg) {
    this.hashAlg = hashAlg;
  }

  /**
   * @return the mgf
   */
  public long getMgf() {
    return mgf;
  }


  /**
   * @param mgf the mgf to set
   */
  public void setMgf(long mgf) {
    this.mgf = mgf;
  }

  /**
   * @return the sLen
   */
  public long getsLen() {
    return sLen;
  }

  /**
   * @param sLen the sLen to set
   */
  public void setsLen(long sLen) {
    this.sLen = sLen;
  }

  /**
   * @return the ulMaxObjectCount
   */
  public long getUlMaxObjectCount() {
    return ulMaxObjectCount;
  }

  /**
   * @param ulMaxObjectCount the ulMaxObjectCount to set
   */
  public void setUlMaxObjectCount(long ulMaxObjectCount) {
    this.ulMaxObjectCount = ulMaxObjectCount;
  }

  /**
   * @return the signFinalArgument
   */
  public int getSignFinalArgument() {
    return signFinalArgument;
  }

  /**
   * @param signFinalArgument the signFinalArgument to set
   */
  public void setSignFinalArgument(int signFinalArgument) {
    this.signFinalArgument = signFinalArgument;
  }

  /**
   * @return the id
   */
  public long getId() {
    return id;
  }

  /**
   * @param id the id to set
   */
  public void setId(long id) {
    this.id = id;
  }

}

“”“

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2022-07-19 10:31:18

Java9up不再将标准库放在jar文件(rt.jar等)中,但它们仍然存在。您的问题可能是Java9up还引入了模块(虽然我没有阅读所有的代码,当然也无法在没有硬件的情况下进行测试)。就像在Java中永远一样,您的代码只能通过它的简单名称引用另一个类或接口(或静态成员import ),或者它与您的代码(如果有的话)或特殊包java.lang位于同一个包中,现在在9向上中,您只能访问与您的代码或特殊java.base模块或模块或/或其他模块相同的包,并且/或其他模块显式地允许访问;对旧Java的显式规范库是一个'open‘。

因此,快速解决方案是向java命令中添加(显式或通过_JAVA_OPTS或等效的) --add-opens jdk.crypto.cryptoki/sun.security.pkcs11.*=ALL-UNNAMED --这将产生与运行在8(或更低)上的结果基本相同的结果。

正式的解决方案是将您的代码放在一个模块中--不管是单独的还是与其他相关的代码-- requires (或每个)所需的模块,因为它导出了所需的部件,而我还没有为您的模块检查过。但是,由于您的代码显然还没有在包中,所以将其放入模块将是一些工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72869306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档