I am developing a class in Java that consists of signing a certificate with a timestamp and a .p12 file in Base64 of the SHA-256 hash of the identity of an application.
So far I have the following development:
public class PruebaP12IA {
public static void main(String[] args) {
// TODO Apéndice de método generado automáticamente
String idAplicacion = "idAplicacion";
String ficheroP12 = "PRUEBAS.p12";
char[] password = "password".toCharArray();
String selloTiempo = "http://urlSelloTiempo/inputRequestTSA";
//Calcular el hash SHA-256 de idAplicacion
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(idAplicacion.getBytes());
byte[] hash = messageDigest.digest();
//Cargar el certificado
InputStream inStream = new FileInputStream(ficheroP12);
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(inStream, password);
String alias = ks.aliases().nextElement();
X509Certificate certificate = (X509Certificate) ks.getCertificate(alias);
//Agregamos el sello de tiempo
TimeStampToken token = new TimeStampToken(new CMSSignedData(selloTiempo.getBytes()));
X509CertificateHolder holder = new X509CertificateHolder(certificate.getEncoded());
/*SignerInformationVerifier siv =
new BcRSASignerInfoVerifierBuilder(new DefaultDigestAlgorithmIdentifierFinder(), new BcDigestCalculatorProvider()).build(holder);*/
DefaultCMSSignatureAlgorithmNameGenerator nameGen = new DefaultCMSSignatureAlgorithmNameGenerator();
DefaultSignatureAlgorithmIdentifierFinder sigAlgofinder = new DefaultSignatureAlgorithmIdentifierFinder();
DefaultDigestAlgorithmIdentifierFinder hashAlgoFinder = new DefaultDigestAlgorithmIdentifierFinder();
BcDigestCalculatorProvider calculator = new BcDigestCalculatorProvider();
BcRSASignerInfoVerifierBuilder verifierBuilder = new BcRSASignerInfoVerifierBuilder(nameGen, sigAlgofinder, hashAlgoFinder, calculator);
SignerInformationVerifier verifier = verifierBuilder.build(holder);
token.validate(verifier);
//Firmar el hash con la clave privada
PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password);
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initSign(privateKey);
signature.update(hash);
byte[] signedHash = signature.sign();
//Verificar firma
PublicKey publicKey = certificate.getPublicKey();
Signature verificacion = Signature.getInstance("SHA256WithRSA");
verificacion.initVerify(publicKey);
verificacion.update(hash);
boolean isValid = verificacion.verify(signedHash);
if(isValid) {
//Enconde the signed certificate in base64
String signedCertificateBase64 = Base64.getEncoder().encodeToString(signedHash);
//Mostrar el certificado firmado en base64
System.out.println("Firma en BASE64: " + signedCertificateBase64);
}
}
}
Without the Agregamos el sello de tiempo part it works perfectly for me, but when I add it (it's necessary) it fails for me on the line TimeStampToken token = new TimeStampToken(new CMSSignedData(timestamp.getBytes())); . The following error occurs:
org.bouncycastle.cms.CMSException: IOException reading content. at org.bouncycastle.cms.CMSUtils.readContentInfo(Unknown Source) at org.bouncycastle.cms.CMSUtils.readContentInfo(Unknown Source) at org.bouncycastle.cms.CMSSignedData.(Unknown Source) at pruebasborrar.PruebaP12IA.main(PruebaP12IA.java:61) Caused by: java.io.EOFException: DEF length 116 object truncated by 67 at org.bouncycastle.asn1.DefiniteLengthInputStream.toByteArray(Unknown Source) at org.bouncycastle.asn1.ASN1InputStream.buildObject(Unknown Source) at org.bouncycastle.asn1.ASN1InputStream.readObject(Unknown Source) ... 4 more
Can anybody help me?
Thanks