Witam,
Jakoś udało mi się znaleźć ten wątek dokładnie powiązany z moim zadaniem. Mianowicie, muszę dopisać do swojej aplikacji możliwość podpisu elektronicznego kwalifikowanego. Używam urządzenia SMART CARD READER ACR38 z Unizeto. Komunikację z czytnikiem ustawiłem i udało mi się podpisać plik używając providera BouncyCastle, ale zapisuje nim do formatu p7m, gdzie razem z podpisem elektronicznym jest dołączony plik źródłowy. Takie rozwiązanie za bardzo mnie nie interesuje, bo potrzebuje stałego dostępu do źródłowego pliku.
Chciałbym to zrobić metodą opisaną w wątkach powyżej. Czy mogę prosić o jakieś wskazówki, ewentualnie przykładowy kod jak wygenerować plik XML z podpisem i ewentualnie jak go później weryfikować?
To co zrobiłem na podstawie kodu powyżej:
Kod:
String pkcs11ConfigSettings = "";
pkcs11ConfigSettings += "name = SmartCard\n";
pkcs11ConfigSettings += "library = E:\\cryptoCertum3PKCS.dll\n";
ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11ConfigSettings.getBytes());
// Instantiate the provider dynamically with Java reflection
Class sunPkcs11Class = Class.forName("sun.security.pkcs11.SunPKCS11");
java.lang.reflect.Constructor pkcs11Constr = sunPkcs11Class.getConstructor(InputStream.class);
Provider pkcs11Provider = (Provider) pkcs11Constr.newInstance(confStream);
Security.addProvider(pkcs11Provider);
//pkcs11ProviderName = pkcs11Provider.getName();
// info about SC provider
System.out.println("SC Provider info: ");
System.out.println("Name: " + pkcs11Provider.getName());
System.out.println("Info: " + pkcs11Provider.getInfo());
System.out.println("Version: " + pkcs11Provider.getVersion());
char[] pin = "2222".toCharArray();
KeyStore ks = KeyStore.getInstance("pkcs11");
ks.load(null, pin);
String alias = "16783361";
PrivateKey key = (PrivateKey) ks.getKey(alias, pin);
java.security.cert.Certificate[] chain = ks.getCertificateChain(alias);
X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
File src = new File("E:\\img.jpg");
int sizecontent = ( (int) src.length());
byte[] contentData = new byte[sizecontent];
FileInputStream freader = new FileInputStream(src);
freader.read(contentData, 0, sizecontent);
freader.close();
//calculate digest of the input data
byte[] toEncrypt = buildBits(contentData);
byte[] signature = signDocument(toEncrypt,key);
for (int i = 0; i < signature.length; i++) {
System.out.print(signature[i]);
}
i funkcje pomocnicze:
Kod:
private static byte[] signDocument(byte[] aDocument,
PrivateKey aPrivateKey) throws GeneralSecurityException {
Signature signatureAlgorithm =
Signature.getInstance("SHA1withRSA");
signatureAlgorithm.initSign(aPrivateKey);
signatureAlgorithm.update(aDocument);
byte[] digitalSignature = signatureAlgorithm.sign();
return digitalSignature;
}
public static byte[] buildBits(byte[] bytesToSign) throws
NoSuchAlgorithmException {
MessageDigest hash = MessageDigest.getInstance("SHA1");
hash.update(bytesToSign);
byte[] digest = hash.digest();
/*
The DSI (Digital Signature Input for RSA) format according to PKCS #1 V1.5
(Block Type 1) has the following structure:
- Startbyte: ?00?
- Block type: ?01?
- Padding-String: ?FF ?FF?
- Separator: ?00?
- DigestInfo: ASN.1-Sequence of digestAlgorithm (ASN.1-Sequence of OID and parameter)
and digest (ASN.1-DO hash value)
The DigestInfo to be delivered to the card has the following coding:
SHA-1 with OID: { 1 3 14 3 2 26 }
DigestInfo: 3021 3009 06052B0E03021A 0500 0414 || hash value (20 bytes)
*/
String hhStr =
"30213009" +
"06052b0e03021a" + //algoritm SHA-1 1.3.14.3.2.26
"0500" +
"0414" + toHexString(digest);
return parse(hhStr);
}
public static byte[] parse(String hexString) {
byte[] ret = new byte[hexString.length() / 2];
for (int i = 0; i < ret.length; i++) {
ret[i] = (byte) Integer.parseInt(hexString.substring(2 * i, 2 * (i + 1)), 16);
}
return ret;
}
public static String toHexString(byte[] arrayHex) {
return toHexString(arrayHex, 0, arrayHex.length);
}
public static String toHexString(byte[] arrayHex, int start, int length) {
String ret = "";
String dd = "";
for (int i = start; i < length; i++) {
int v = 0;
dd = "";
v = (int) arrayHex[i];
if (v < 0) {
v += 256;
}
dd = Integer.toHexString(v).toUpperCase();
if (dd.length() == 1) {
dd = "0" + dd;
}
ret += dd;
}
return ret;
}
Za wszelką pomoc z góry dziękuje

Pozdrawiam