I have Escrypt Smart Card to sign data bytes and get signature and certificate for it.
I have java tool to do it and everything was fine until Java 8. Now application migrated to Java 11. And problem start from here.
- SunPKCS11.jar/ library is not a part of Java 11, hence application breaks.
- I tried with different solution available over internet and oracle release notes, it suggest to use
java.security
package for cryptographic operation.
I am not able to switch from Java 8 to java 11, any support would be really useful.
Edit-1: Minimum usable code
- Signature calculator is used to parse signature
- It is written with Java 8 & SunPKCS11.jar want to migrate it to Java 11
'''
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;
}
}
'''
Thank You!