Using PBEFileProcessor to decrypt file provided by bouncycastle - java

I am facing some issue in decrypting a pgp encrypted file. I have the pass phase and the file with me. Now to decrypt it I need to use a class PBEFileProcessor (best guess) provided by bouncycastle in their jar. I have included the jar in my eclipse project and have made a new class which calls this class to decrypt the file. But i am having hard time debugging it.
The code for the same is:
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.security.NoSuchProviderException;import java.security.SecureRandom;import java.security.Security;import org.bouncycastle.bcpg.ArmoredOutputStream;import org.bouncycastle.bcpg.CompressionAlgorithmTags;import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;import org.bouncycastle.jce.provider.BouncyCastleProvider;import org.bouncycastle.openpgp.PGPCompressedData;import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;import org.bouncycastle.openpgp.PGPEncryptedDataList;import org.bouncycastle.openpgp.PGPException;import org.bouncycastle.openpgp.PGPLiteralData;import org.bouncycastle.openpgp.PGPPBEEncryptedData;import org.bouncycastle.openpgp.PGPUtil;import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;import rg.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;import org.bouncycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder;import org.bouncycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator;import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;import org.bouncycastle.util.io.Streams;
public class PBEFileProcessor1 {
private static void decryptFile(String inputFileName, char[] passPhrase)
throws IOException, NoSuchProviderException, PGPException
{
InputStream in = new BufferedInputStream(new FileInputStream(inputFileName));
decryptFile(in, passPhrase);
in.close();
}
/*
* decrypt the passed in message stream
*/
private static void decryptFile(
InputStream in,
char[] passPhrase)
throws IOException, NoSuchProviderException, PGPException
{
in = PGPUtil.getDecoderStream(in);
JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
if (o instanceof PGPEncryptedDataList)
{
enc = (PGPEncryptedDataList)o;
}
else
{
enc = (PGPEncryptedDataList)pgpF.nextObject();
}
PGPPBEEncryptedData pbe = (PGPPBEEncryptedData)enc.get(0);
InputStream clear = pbe.getDataStream(new JcePBEDataDecryptorFactoryBuilder(new JcaPGPDigestCalculatorProviderBuilder().setProvider("BC").build()).setProvider("BC").build(passPhrase));
JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(clear);
//
// if we're trying to read a file generated by someone other than us
// the data might not be compressed, so we check the return type from
// the factory and behave accordingly.
//
o = pgpFact.nextObject();
if (o instanceof PGPCompressedData)
{
PGPCompressedData cData = (PGPCompressedData)o;
pgpFact = new JcaPGPObjectFactory(cData.getDataStream());
o = pgpFact.nextObject();
}
PGPLiteralData ld = (PGPLiteralData)o;
InputStream unc = ld.getInputStream();
OutputStream fOut = new BufferedOutputStream(new FileOutputStream(ld.getFileName()));
Streams.pipeAll(unc, fOut);
fOut.close();
if (pbe.isIntegrityProtected())
{
if (!pbe.verify())
{
System.err.println("message failed integrity check");
}
else
{
System.err.println("message integrity check passed");
}
}
else
{
System.err.println("no message integrity check");
}
}
private static void encryptFile(
String outputFileName,
String inputFileName,
char[] passPhrase,
boolean armor,
boolean withIntegrityCheck)
throws IOException, NoSuchProviderException
{
OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFileName));
encryptFile(out, inputFileName, passPhrase, armor, withIntegrityCheck);
out.close();
}
private static void encryptFile(
OutputStream out,
String fileName,
char[] passPhrase,
boolean armor,
boolean withIntegrityCheck)
throws IOException, NoSuchProviderException
{
if (armor)
{
out = new ArmoredOutputStream(out);
}
try
{
byte[] compressedData = BouncyCastlePGPExampleUtil.compressFile(fileName, CompressionAlgorithmTags.ZIP);
PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.CAST5)
.setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC"));
encGen.addMethod(new JcePBEKeyEncryptionMethodGenerator(passPhrase).setProvider("BC"));
OutputStream encOut = encGen.open(out, compressedData.length);
encOut.write(compressedData);
encOut.close();
if (armor)
{
out.close();
}
}
catch (PGPException e)
{
System.err.println(e);
if (e.getUnderlyingException() != null)
{
e.getUnderlyingException().printStackTrace();
}
}
}
public static void main(
String[] args)
throws Exception
{
Security.addProvider(new BouncyCastleProvider());
if (args[0].equals("-e"))
{
if (args[1].equals("-a") || args[1].equals("-ai") || args[1].equals("-ia"))
{
encryptFile(args[2] + ".asc", args[2], args[3].toCharArray(), true, (args[1].indexOf('i') > 0));
}
else if (args[1].equals("-i"))
{
encryptFile(args[2] + ".bpg", args[2], args[3].toCharArray(), false, true);
}
else
{
encryptFile(args[1] + ".bpg", args[1], args[2].toCharArray(), false, false);
}
}
else if (args[0].equals("-d"))
{
decryptFile(args[1], args[2].toCharArray());
}
else
{
System.err.println("usage: PBEFileProcessor -e [-ai]|-d file passPhrase");
}
}
}
The java terminal command is : C:\Users\anirudgu\eclipse-workspace\Decryptfile\bin>java PBEFileProcessor1 -d C:\Users\anirudgu\eclipse-workspace\Decryptfile\bin\PTO_data_26_06_2019_16_04.csv Passphase
But the error I am receiving is
Exception in thread "main" java.lang.ClassCastException: org.bouncycastle.openpgp.PGPPublicKeyEncryptedData cannot be cast to org.bouncycastle.openpgp.PGPPB
EEncryptedData
at PBEFileProcessor1.decryptFile(PBEFileProcessor1.java:90)
at PBEFileProcessor1.decryptFile(PBEFileProcessor1.java:60)
at PBEFileProcessor1.main(PBEFileProcessor1.java:215)
But I am able to encrypt this file with the same code.
The jar file that are used are available here

Related

Base64 digest + PFX(PKCS12) -> ETSI.CAdES.detached signature -> PAdES LTV

I have an API that creates Base64 digest of a PDF Document.
Now I want to create another API that takes this digest and PFX and creates an ETSI.CAdES.detached signature and takes LTV informations(Certs chain,OCSP response,CRL) that I want to embed in my PDF to obtain a PAdES-LTV signature using 3rd API(My 3rd API will take CAdES signature and LTV informations obtained from this API and will embed them in my PDF).I dont know how to create this ETSI.CAdES.detached signature using that digest and a PFX with Java and Bouncy Castle.I try to follow this github tutorial.
As you have declared, you have your own code for preparing a PDF for signing and for injecting the signature container into it. Thus, your question essentially burns down to
How to create a CAdES signature container with BouncyCastle that can be used to create a PAdES BASELINE B or T PDF signature?
Implementation in the iText 7 Signing Framework
As I do not have your existing code, I had to use a different framework for my tests. I used the iText 7 signing framework for that.
BouncyCastle does contain a CMSSignedDataGenerator to generate CMS signature containers.
The default implementation of the SignerInfo generation therein unfortunately is not CAdES/PAdES compatible as it does not create signed ESSCertID[v2] attributes. Fortunately, though, the implementation is designed to allow plugging in custom attributes sets.
Thus, you can create the CAdES containers required for PAdES BASELINE signatures with a customized CMSSignedDataGenerator.
So when you have prepared the PDF for signing, you can proceed like this:
InputStream data = [InputStream containing the PDF byte ranges to sign];
ContentSigner contentSigner = [BouncyCastle ContentSigner for your private key];
X509CertificateHolder x509CertificateHolder = [BouncyCastle X509CertificateHolder for your X.509 signer certificate];
DigestCalculatorProvider digestCalculatorProvider = new JcaDigestCalculatorProviderBuilder().setProvider("BC").build();
CMSTypedData msg = new CMSTypedDataInputStream(data);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
gen.addSignerInfoGenerator(
new JcaSignerInfoGeneratorBuilder(digestCalculatorProvider)
.setSignedAttributeGenerator(new PadesSignedAttributeGenerator())
.setUnsignedAttributeGenerator(new PadesUnsignedAttributeGenerator())
.build(contentSigner, x509CertificateHolder));
gen.addCertificates(new JcaCertStore(Collections.singleton(x509CertificateHolder)));
CMSSignedData sigData = gen.generate(msg, false);
byte[] cmsBytes = sigData.getEncoded();
(PadesSignatureContainerBc method sign)
The byte[] cmsBytes contains the bytes to inject into the prepared PDF signature placeholder.
The following helper classes are needed:
First of all a wrapper for the InputStream containing the PDF ranges to sign to process by BouncyCastle.
class CMSTypedDataInputStream implements CMSTypedData {
InputStream in;
public CMSTypedDataInputStream(InputStream is) {
in = is;
}
#Override
public ASN1ObjectIdentifier getContentType() {
return PKCSObjectIdentifiers.data;
}
#Override
public Object getContent() {
return in;
}
#Override
public void write(OutputStream out) throws IOException,
CMSException {
byte[] buffer = new byte[8 * 1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
}
}
(PadesSignatureContainerBc helper class CMSTypedDataInputStream)
Then a customized signed attributes generator for PAdES:
class PadesSignedAttributeGenerator implements CMSAttributeTableGenerator {
#Override
public AttributeTable getAttributes(#SuppressWarnings("rawtypes") Map params) throws CMSAttributeTableGenerationException {
String currentAttribute = null;
try {
ASN1EncodableVector signedAttributes = new ASN1EncodableVector();
currentAttribute = "SigningCertificateAttribute";
AlgorithmIdentifier digAlgId = (AlgorithmIdentifier) params.get(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER);
signedAttributes.add(createSigningCertificateAttribute(digAlgId));
currentAttribute = "ContentTypeAttribute";
ASN1ObjectIdentifier contentType = ASN1ObjectIdentifier.getInstance(params.get(CMSAttributeTableGenerator.CONTENT_TYPE));
signedAttributes.add(new Attribute(CMSAttributes.contentType, new DERSet(contentType)));
currentAttribute = "MessageDigestAttribute";
byte[] messageDigest = (byte[])params.get(CMSAttributeTableGenerator.DIGEST);
signedAttributes.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(messageDigest))));
return new AttributeTable(signedAttributes);
} catch (Exception e) {
throw new CMSAttributeTableGenerationException(currentAttribute, e);
}
}
Attribute createSigningCertificateAttribute(AlgorithmIdentifier digAlg) throws IOException, OperatorCreationException {
final IssuerSerial issuerSerial = getIssuerSerial();
DigestCalculator digestCalculator = digestCalculatorProvider.get(digAlg);
digestCalculator.getOutputStream().write(x509CertificateHolder.getEncoded());
final byte[] certHash = digestCalculator.getDigest();
if (OIWObjectIdentifiers.idSHA1.equals(digAlg.getAlgorithm())) {
final ESSCertID essCertID = new ESSCertID(certHash, issuerSerial);
SigningCertificate signingCertificate = new SigningCertificate(essCertID);
return new Attribute(id_aa_signingCertificate, new DERSet(signingCertificate));
} else {
ESSCertIDv2 essCertIdv2;
if (NISTObjectIdentifiers.id_sha256.equals(digAlg.getAlgorithm())) {
// SHA-256 is default
essCertIdv2 = new ESSCertIDv2(null, certHash, issuerSerial);
} else {
essCertIdv2 = new ESSCertIDv2(digAlg, certHash, issuerSerial);
}
SigningCertificateV2 signingCertificateV2 = new SigningCertificateV2(essCertIdv2);
return new Attribute(id_aa_signingCertificateV2, new DERSet(signingCertificateV2));
}
}
IssuerSerial getIssuerSerial() {
final X500Name issuerX500Name = x509CertificateHolder.getIssuer();
final GeneralName generalName = new GeneralName(issuerX500Name);
final GeneralNames generalNames = new GeneralNames(generalName);
final BigInteger serialNumber = x509CertificateHolder.getSerialNumber();
return new IssuerSerial(generalNames, serialNumber);
}
}
(PadesSignatureContainerBc helper class PadesSignedAttributeGenerator )
And finally a customized unsigned attributes generator for a signature timestamp:
class PadesUnsignedAttributeGenerator implements CMSAttributeTableGenerator {
#Override
public AttributeTable getAttributes(#SuppressWarnings("rawtypes") Map params) throws CMSAttributeTableGenerationException {
if (tsaClient == null)
return null;
try {
ASN1EncodableVector unsignedAttributes = new ASN1EncodableVector();
byte[] signature = (byte[])params.get(CMSAttributeTableGenerator.SIGNATURE);
byte[] timestamp = tsaClient.getTimeStampToken(tsaClient.getMessageDigest().digest(signature));
unsignedAttributes.add(new Attribute(id_aa_signatureTimeStampToken, new DERSet(ASN1Primitive.fromByteArray(timestamp))));
return new AttributeTable(unsignedAttributes);
} catch (Exception e) {
throw new CMSAttributeTableGenerationException("", e);
}
}
}
(PadesSignatureContainerBc helper class PadesUnsignedAttributeGenerator)
Here I assume a ITSAClient tsaClient, an iText 7 time stamp request client. You can of course use an arbitrary RFC 3161 time stamp request client of your choice.
If you have read your private key into a JCA/JCE PrivateKey pk, you can simply create the needed ContentSigner contentSigner using the BouncyCastle JcaContentSignerBuilder, e.g. like this:
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA512withRSA").build(pk);
(compare the test testSignPadesBaselineT in SignPadesBc)
Implementation in the PDFBox 3 Signing Framework
You meanwhile indicated in comments that you're looking into using PDFBox to sign. Fortunately the code presented above can nearly without a change be used with PDFBox.
To use the code above with PDFBox, one merely has to wrap it into a PDFBox SignatureInterface frame:
public class PadesSignatureContainerBc implements SignatureInterface {
public PadesSignatureContainerBc(X509CertificateHolder x509CertificateHolder, ContentSigner contentSigner, TSAClient tsaClient) throws OperatorCreationException {
this.contentSigner = contentSigner;
this.tsaClient = tsaClient;
this.x509CertificateHolder = x509CertificateHolder;
digestCalculatorProvider = new JcaDigestCalculatorProviderBuilder().setProvider("BC").build();
}
#Override
public byte[] sign(InputStream content) throws IOException {
try {
CMSTypedData msg = new CMSTypedDataInputStream(content);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
gen.addSignerInfoGenerator(
new JcaSignerInfoGeneratorBuilder(digestCalculatorProvider)
.setSignedAttributeGenerator(new PadesSignedAttributeGenerator())
.setUnsignedAttributeGenerator(new PadesUnsignedAttributeGenerator())
.build(contentSigner, x509CertificateHolder));
gen.addCertificates(new JcaCertStore(Collections.singleton(x509CertificateHolder)));
CMSSignedData sigData = gen.generate(msg, false);
return sigData.getEncoded();
} catch (OperatorCreationException | GeneralSecurityException | CMSException e) {
throw new IOException(e);
}
}
final ContentSigner contentSigner;
final X509CertificateHolder x509CertificateHolder;
final TSAClient tsaClient;
final DigestCalculatorProvider digestCalculatorProvider;
class CMSTypedDataInputStream implements CMSTypedData {
InputStream in;
public CMSTypedDataInputStream(InputStream is) {
in = is;
}
#Override
public ASN1ObjectIdentifier getContentType() {
return PKCSObjectIdentifiers.data;
}
#Override
public Object getContent() {
return in;
}
#Override
public void write(OutputStream out) throws IOException,
CMSException {
byte[] buffer = new byte[8 * 1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
}
}
class PadesSignedAttributeGenerator implements CMSAttributeTableGenerator {
#Override
public AttributeTable getAttributes(#SuppressWarnings("rawtypes") Map params) throws CMSAttributeTableGenerationException {
String currentAttribute = null;
try {
ASN1EncodableVector signedAttributes = new ASN1EncodableVector();
currentAttribute = "SigningCertificateAttribute";
AlgorithmIdentifier digAlgId = (AlgorithmIdentifier) params.get(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER);
signedAttributes.add(createSigningCertificateAttribute(digAlgId));
currentAttribute = "ContentType";
ASN1ObjectIdentifier contentType = ASN1ObjectIdentifier.getInstance(params.get(CMSAttributeTableGenerator.CONTENT_TYPE));
signedAttributes.add(new Attribute(CMSAttributes.contentType, new DERSet(contentType)));
currentAttribute = "MessageDigest";
byte[] messageDigest = (byte[])params.get(CMSAttributeTableGenerator.DIGEST);
signedAttributes.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(messageDigest))));
return new AttributeTable(signedAttributes);
} catch (Exception e) {
throw new CMSAttributeTableGenerationException(currentAttribute, e);
}
}
Attribute createSigningCertificateAttribute(AlgorithmIdentifier digAlg) throws IOException, OperatorCreationException {
final IssuerSerial issuerSerial = getIssuerSerial();
DigestCalculator digestCalculator = digestCalculatorProvider.get(digAlg);
digestCalculator.getOutputStream().write(x509CertificateHolder.getEncoded());
final byte[] certHash = digestCalculator.getDigest();
if (OIWObjectIdentifiers.idSHA1.equals(digAlg.getAlgorithm())) {
final ESSCertID essCertID = new ESSCertID(certHash, issuerSerial);
SigningCertificate signingCertificate = new SigningCertificate(essCertID);
return new Attribute(id_aa_signingCertificate, new DERSet(signingCertificate));
} else {
ESSCertIDv2 essCertIdv2;
if (NISTObjectIdentifiers.id_sha256.equals(digAlg.getAlgorithm())) {
// SHA-256 is default
essCertIdv2 = new ESSCertIDv2(null, certHash, issuerSerial);
} else {
essCertIdv2 = new ESSCertIDv2(digAlg, certHash, issuerSerial);
}
SigningCertificateV2 signingCertificateV2 = new SigningCertificateV2(essCertIdv2);
return new Attribute(id_aa_signingCertificateV2, new DERSet(signingCertificateV2));
}
}
public IssuerSerial getIssuerSerial() {
final X500Name issuerX500Name = x509CertificateHolder.getIssuer();
final GeneralName generalName = new GeneralName(issuerX500Name);
final GeneralNames generalNames = new GeneralNames(generalName);
final BigInteger serialNumber = x509CertificateHolder.getSerialNumber();
return new IssuerSerial(generalNames, serialNumber);
}
}
class PadesUnsignedAttributeGenerator implements CMSAttributeTableGenerator {
#Override
public AttributeTable getAttributes(#SuppressWarnings("rawtypes") Map params) throws CMSAttributeTableGenerationException {
if (tsaClient == null)
return null;
try {
ASN1EncodableVector unsignedAttributes = new ASN1EncodableVector();
byte[] signature = (byte[])params.get(CMSAttributeTableGenerator.SIGNATURE);
byte[] timestamp = tsaClient.getTimeStampToken(new ByteArrayInputStream(signature)).getEncoded();
unsignedAttributes.add(new Attribute(id_aa_signatureTimeStampToken, new DERSet(ASN1Primitive.fromByteArray(timestamp))));
return new AttributeTable(unsignedAttributes);
} catch (Exception e) {
throw new CMSAttributeTableGenerationException("", e);
}
}
}
}
(PDFBox PadesSignatureContainerBc implementation of SignatureInterface)
You can use it like this
try ( PDDocument pdDocument = Loader.loadPDF(SOURCE_PDF) )
{
SignatureInterface signatureInterface = new PadesSignatureContainerBc(new X509CertificateHolder(chain[0].getEncoded()),
new JcaContentSignerBuilder("SHA512withRSA").build(pk),
new TSAClient(new URL("http://timestamp.server/rfc3161endpoint"), null, null, MessageDigest.getInstance("SHA-256")));
PDSignature signature = new PDSignature();
signature.setFilter(COSName.getPDFName("MKLx_PAdES_SIGNER"));
signature.setSubFilter(COSName.getPDFName("ETSI.CAdES.detached"));
signature.setName("Example User");
signature.setLocation("Los Angeles, CA");
signature.setReason("Testing");
signature.setSignDate(Calendar.getInstance());
pdDocument.addSignature(signature);
ExternalSigningSupport externalSigning = pdDocument.saveIncrementalForExternalSigning(RESULT_OUTPUT);
// invoke external signature service
byte[] cmsSignature = signatureInterface.sign(externalSigning.getContent());
// set signature bytes received from the service
externalSigning.setSignature(cmsSignature);
}
(PDFBox SignPadesBc test testSignPadesBaselineT)

Error to validate ECDSA signature in pkcs7

I have successfully generate pkcs7 signature ECDSAwithSHA256 using C# , but then i failed to verify signature using java
Here is sample class
public class TestVerify {
public static void main(String[] args) {
String Signature = "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";
String SigDateTime = "14-10-2020 10:58:22";
String certtype = "token";
String TimestampToken = "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";
String pdfhash = "faadTnFU4cOBsl+sW98ie7KInSbbw0HDbgFeOcsRCAQ=";
CMSSignedData signedDataTSToken = null;
TimeStampToken tstoken = null;
byte[] sigDataBytes = null;
Date sigDate = null;
CMSSignerHelper cmsHelper = new CMSSignerHelper();
CMSSignedData cmsData;
try {
sigDataBytes = Base64.getDecoder().decode(Signature);
cmsData = new CMSSignedData(sigDataBytes);
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
sigDate = formatter.parse(SigDateTime);
byte[] tsTokenDataBytes = Base64.getDecoder().decode(TimestampToken);
signedDataTSToken = new CMSSignedData(tsTokenDataBytes);
tstoken = new TimeStampToken(signedDataTSToken);
verifyCMSSignatureMTID(sigDataBytes, sigDate, TimestampToken, pdfhash);
} catch (Exception e) {
System.out.println("Exception : " + e);
}
}
public static void verifyCMSSignatureMTID(byte[] signature, Date signing_date, String encodedTimestampToken, String PdfHash) throws OperatorCreationException, CMSException, CertificateException, NoSuchAlgorithmException, ParseException, TSPException, IOException, Exception {
String fName="[verifyCMSSignatureMTID] ";
VSInfo vsi=new VSInfo();
String initErr="CMS";
//******************** VERIFY SGNATURE VS SIGNER PUBLICKEY **********************
// Verify signature
byte[] HashByte = Base64.getDecoder().decode(PdfHash);
CMSProcessableByteArray processable = new CMSProcessableByteArray(HashByte);
CMSSignedData cmsData = new CMSSignedData(signature);
X509CertificateHolder certHolder_v=null;
Security.addProvider(new BouncyCastleProvider());
try {
Store store = cmsData.getCertificates();
ByteArrayInputStream stream = new ByteArrayInputStream(signature);
CMSSignedData cms = new CMSSignedData(processable, stream);
SignerInformationStore signers = cms.getSignerInfos();
Collection c_v = signers.getSigners();
Iterator it_v = c_v.iterator();
while (it_v.hasNext()) {
SignerInformation signer_v = (SignerInformation) it_v.next();
Collection certCollection_v = store.getMatches(signer_v.getSID());
Iterator certIt_v = certCollection_v.iterator();
certHolder_v = (X509CertificateHolder) certIt_v.next();
X509Certificate certFromSignedData_v = new JcaX509CertificateConverter().getCertificate(certHolder_v);
if (signer_v.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BouncyCastleProvider.PROVIDER_NAME).build(certFromSignedData_v))) {
System.out.println(fName + "Signature verified");
} else {
System.out.println(fName + "Error CMS200 Signature is invalid");
System.out.println(initErr+"200");
System.out.println("Signature is invalid");
return;
}
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(fName + "Error CMS200 Signature is invalid : " + e);
System.out.println("200");
System.out.println("Signature is invalid");
return;
}
System.out.println("000");
System.out.println("Signature is valid");
return;
}
}
Error
org.bouncycastle.operator.RuntimeOperatorException: exception
obtaining signature: error decoding signature bytes.
However, i have succesfully verify RSAwithSHA256 signature using this method. Can someone help me on this and kindly explain what that error is about. The signature length for those signature is 256byte for RSA and 64byte for ECDSA . is it correct?

iText7 LtvVerification.addVerification not enabling LTV

We are trying to make the signed signature LTV enabled. I am using the below code to add verification. When signature.isTsp() is false, the PDF says Signature is not LTV enabled, though in the other case (signature.isTsp() is true) it shows as valid.
When we open the PDF and try to manually add verification info by right clicking on the signature it enables LTV without any issue. Not sure what we are missing here.
Any input will be highly helpful.
// Adds LTV-enabled information to the PDF document.
private ByteArrayOutputStream addLtv(final IOcspClient ocspClient,
final ByteArrayOutputStream docStream)
throws IOException, GeneralSecurityException {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final InputStream signedStream = new ByteArrayInputStream(docStream.toByteArray());
final PdfReader reader = new PdfReader(signedStream);
final PdfDocument document =
new PdfDocument(reader, new PdfWriter(outputStream), new StampingProperties().useAppendMode());
final LtvVerification verification = new LtvVerification(document);
final SignatureUtil signatureUtil = new SignatureUtil(document);
final List<String> signatureNames = signatureUtil.getSignatureNames();
final String sigName = signatureNames.get(signatureNames.size() - 1);
final PdfPKCS7 signature = signatureUtil.verifySignature(sigName);
final CrlClientOnline crl = new CrlClientOnline();
if (!signature.isTsp()) {
for (final String name: signatureNames) {
addVerificationInfo(ocspClient, verification, crl, name);
}
} else {
addVerificationInfo(ocspClient, verification, crl, sigName);
}
document.close();
return outputStream;
}
private void addVerificationInfo(final IOcspClient ocspClient, final LtvVerification verification,
final CrlClientOnline crl,
final String name) throws IOException, GeneralSecurityException {
verification.addVerification(
name, ocspClient, crl,
LtvVerification.CertificateOption.WHOLE_CHAIN,
LtvVerification.Level.OCSP_CRL,
LtvVerification.CertificateInclusion.NO);
}
The main reason why your code does not always LTV-enable PDFs is that it does not add validation information related to OCSP response signatures.
It doesn't add validation information for CRL signatures, either. As CRLs usually are signed by the issuer certificate of the signer certificate, though, and as validation information for that issuer certificate have already been added in the context of the main signature, LTV-enabling usually does not fail because of missing CRL signature validation information. So if you can use CRLs only, chances are that your code indeed already does LTV-enable PDFs.
In the context of this answer (in particular its section "An approach using an own utility class") I created an utility class AdobeLtvEnabling for iText 5 allowing to LTV-enable PDFs, mostly using bits and pieces found in iText 5 itself. In contrast to your code it does add validation information for OCSP response signatures (and also for CRL signatures).
Here you can find the port of that class to iText 7.
The utility class AdobeLtvEnabling
This utility class bundles the code required for LTV enabling the signatures in a signed PDF document. The code pieces mostly have been taken from existing iText code. The main reason why this class has not been designed to derive from LtvVerification is that required variables and methods from that class are private. As the class originally has been written for iText 5, some iText-5-isms probably can be found in it...
public class AdobeLtvEnabling {
/**
* Use this constructor with a {#link PdfDocument} in append mode. Otherwise
* the existing signatures will be damaged.
*/
public AdobeLtvEnabling(PdfDocument pdfDocument) {
this.pdfDocument = pdfDocument;
}
/**
* Call this method to have LTV information added to the {#link PdfDocument}
* given in the constructor.
*/
public void enable(IOcspClient ocspClient, ICrlClient crlClient) throws OperatorException, GeneralSecurityException, IOException, StreamParsingException, OCSPException {
SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
List<String> names = signatureUtil.getSignatureNames();
for (String name : names) {
PdfPKCS7 pdfPKCS7 = signatureUtil.verifySignature(name, BouncyCastleProvider.PROVIDER_NAME);
PdfSignature sig = signatureUtil.getSignature(name);
List<X509Certificate> certificatesToCheck = new ArrayList<>();
certificatesToCheck.add(pdfPKCS7.getSigningCertificate());
while (!certificatesToCheck.isEmpty()) {
X509Certificate certificate = certificatesToCheck.remove(0);
addLtvForChain(certificate, ocspClient, crlClient, getSignatureHashKey(sig));
}
}
outputDss();
}
//
// the actual LTV enabling methods
//
void addLtvForChain(X509Certificate certificate, IOcspClient ocspClient, ICrlClient crlClient, PdfName key) throws GeneralSecurityException, IOException, StreamParsingException, OperatorCreationException, OCSPException {
ValidationData validationData = new ValidationData();
while (certificate != null) {
System.out.println(certificate.getSubjectX500Principal().getName());
X509Certificate issuer = getIssuerCertificate(certificate);
validationData.certs.add(certificate.getEncoded());
byte[] ocspResponse = ocspClient.getEncoded(certificate, issuer, null);
if (ocspResponse != null) {
System.out.println(" with OCSP response");
validationData.ocsps.add(ocspResponse);
X509Certificate ocspSigner = getOcspSignerCertificate(ocspResponse);
if (ocspSigner != null) {
System.out.printf(" signed by %s\n", ocspSigner.getSubjectX500Principal().getName());
}
addLtvForChain(ocspSigner, ocspClient, crlClient, getOcspHashKey(ocspResponse));
} else {
Collection<byte[]> crl = crlClient.getEncoded(certificate, null);
if (crl != null && !crl.isEmpty()) {
System.out.printf(" with %s CRLs\n", crl.size());
validationData.crls.addAll(crl);
for (byte[] crlBytes : crl) {
addLtvForChain(null, ocspClient, crlClient, getCrlHashKey(crlBytes));
}
}
}
certificate = issuer;
}
validated.put(key, validationData);
}
void outputDss() throws IOException {
PdfDictionary dss = new PdfDictionary();
PdfDictionary vrim = new PdfDictionary();
PdfArray ocsps = new PdfArray();
PdfArray crls = new PdfArray();
PdfArray certs = new PdfArray();
PdfCatalog catalog = pdfDocument.getCatalog();
if (pdfDocument.getPdfVersion().compareTo(PdfVersion.PDF_2_0) < 0) {
catalog.addDeveloperExtension(PdfDeveloperExtension.ESIC_1_7_EXTENSIONLEVEL5);
catalog.addDeveloperExtension(new PdfDeveloperExtension(PdfName.ADBE, new PdfName("1.7"), 8));
}
for (PdfName vkey : validated.keySet()) {
PdfArray ocsp = new PdfArray();
PdfArray crl = new PdfArray();
PdfArray cert = new PdfArray();
PdfDictionary vri = new PdfDictionary();
for (byte[] b : validated.get(vkey).crls) {
PdfStream ps = new PdfStream(b);
ps.setCompressionLevel(CompressionConstants.DEFAULT_COMPRESSION);
ps.makeIndirect(pdfDocument);
crl.add(ps);
crls.add(ps);
crls.setModified();
}
for (byte[] b : validated.get(vkey).ocsps) {
b = buildOCSPResponse(b);
PdfStream ps = new PdfStream(b);
ps.setCompressionLevel(CompressionConstants.DEFAULT_COMPRESSION);
ps.makeIndirect(pdfDocument);
ocsp.add(ps);
ocsps.add(ps);
ocsps.setModified();
}
for (byte[] b : validated.get(vkey).certs) {
PdfStream ps = new PdfStream(b);
ps.setCompressionLevel(CompressionConstants.DEFAULT_COMPRESSION);
ps.makeIndirect(pdfDocument);
cert.add(ps);
certs.add(ps);
certs.setModified();
}
if (ocsp.size() > 0) {
ocsp.makeIndirect(pdfDocument);
vri.put(PdfName.OCSP, ocsp);
}
if (crl.size() > 0) {
crl.makeIndirect(pdfDocument);
vri.put(PdfName.CRL, crl);
}
if (cert.size() > 0) {
cert.makeIndirect(pdfDocument);
vri.put(PdfName.Cert, cert);
}
vri.put(PdfName.TU, new PdfDate().getPdfObject());
vri.makeIndirect(pdfDocument);
vrim.put(vkey, vri);
}
vrim.makeIndirect(pdfDocument);
vrim.setModified();
dss.put(PdfName.VRI, vrim);
if (ocsps.size() > 0) {
ocsps.makeIndirect(pdfDocument);
dss.put(PdfName.OCSPs, ocsps);
}
if (crls.size() > 0) {
crls.makeIndirect(pdfDocument);
dss.put(PdfName.CRLs, crls);
}
if (certs.size() > 0) {
certs.makeIndirect(pdfDocument);
dss.put(PdfName.Certs, certs);
}
dss.makeIndirect(pdfDocument);
dss.setModified();
catalog.put(PdfName.DSS, dss);
}
//
// VRI signature hash key calculation
//
static PdfName getCrlHashKey(byte[] crlBytes) throws NoSuchAlgorithmException, IOException, CRLException, CertificateException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509CRL crl = (X509CRL)cf.generateCRL(new ByteArrayInputStream(crlBytes));
byte[] signatureBytes = crl.getSignature();
DEROctetString octetString = new DEROctetString(signatureBytes);
byte[] octetBytes = octetString.getEncoded();
byte[] octetHash = hashBytesSha1(octetBytes);
PdfName octetName = new PdfName(convertToHex(octetHash));
return octetName;
}
static PdfName getOcspHashKey(byte[] basicResponseBytes) throws NoSuchAlgorithmException, IOException {
BasicOCSPResponse basicResponse = BasicOCSPResponse.getInstance(basicResponseBytes);
byte[] signatureBytes = basicResponse.getSignature().getBytes();
DEROctetString octetString = new DEROctetString(signatureBytes);
byte[] octetBytes = octetString.getEncoded();
byte[] octetHash = hashBytesSha1(octetBytes);
PdfName octetName = new PdfName(convertToHex(octetHash));
return octetName;
}
static PdfName getSignatureHashKey(PdfSignature sig) throws NoSuchAlgorithmException, IOException {
PdfString contents = sig.getContents();
byte[] bc = PdfEncodings.convertToBytes(contents.getValue(), null);
if (PdfName.ETSI_RFC3161.equals(sig.getSubFilter())) {
try ( ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(bc)) ) {
ASN1Primitive pkcs = din.readObject();
bc = pkcs.getEncoded();
}
}
byte[] bt = hashBytesSha1(bc);
return new PdfName(convertToHex(bt));
}
static byte[] hashBytesSha1(byte[] b) throws NoSuchAlgorithmException {
MessageDigest sh = MessageDigest.getInstance("SHA1");
return sh.digest(b);
}
static String convertToHex(byte[] bytes) {
ByteBuffer buf = new ByteBuffer();
for (byte b : bytes) {
buf.appendHex(b);
}
return PdfEncodings.convertToString(buf.toByteArray(), null).toUpperCase();
}
//
// OCSP response helpers
//
static X509Certificate getOcspSignerCertificate(byte[] basicResponseBytes) throws CertificateException, OCSPException, OperatorCreationException {
JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);
BasicOCSPResponse borRaw = BasicOCSPResponse.getInstance(basicResponseBytes);
BasicOCSPResp bor = new BasicOCSPResp(borRaw);
for (final X509CertificateHolder x509CertificateHolder : bor.getCerts()) {
X509Certificate x509Certificate = converter.getCertificate(x509CertificateHolder);
JcaContentVerifierProviderBuilder jcaContentVerifierProviderBuilder = new JcaContentVerifierProviderBuilder();
jcaContentVerifierProviderBuilder.setProvider(BouncyCastleProvider.PROVIDER_NAME);
final PublicKey publicKey = x509Certificate.getPublicKey();
ContentVerifierProvider contentVerifierProvider = jcaContentVerifierProviderBuilder.build(publicKey);
if (bor.isSignatureValid(contentVerifierProvider))
return x509Certificate;
}
return null;
}
static byte[] buildOCSPResponse(byte[] BasicOCSPResponse) throws IOException {
DEROctetString doctet = new DEROctetString(BasicOCSPResponse);
ASN1EncodableVector v2 = new ASN1EncodableVector();
v2.add(OCSPObjectIdentifiers.id_pkix_ocsp_basic);
v2.add(doctet);
ASN1Enumerated den = new ASN1Enumerated(0);
ASN1EncodableVector v3 = new ASN1EncodableVector();
v3.add(den);
v3.add(new DERTaggedObject(true, 0, new DERSequence(v2)));
DERSequence seq = new DERSequence(v3);
return seq.getEncoded();
}
//
// X509 certificate related helpers
//
static X509Certificate getIssuerCertificate(X509Certificate certificate) throws IOException, StreamParsingException {
String url = getCACURL(certificate);
if (url != null && url.length() > 0) {
HttpURLConnection con = (HttpURLConnection)new URL(url).openConnection();
if (con.getResponseCode() / 100 != 2) {
throw new PdfException(PdfException.InvalidHttpResponse1).setMessageParams(con.getResponseCode());
}
InputStream inp = (InputStream) con.getContent();
X509CertParser parser = new X509CertParser();
parser.engineInit(new ByteArrayInputStream(StreamUtil.inputStreamToArray(inp)));
return (X509Certificate) parser.engineRead();
}
return null;
}
static String getCACURL(X509Certificate certificate) {
ASN1Primitive obj;
try {
obj = getExtensionValue(certificate, Extension.authorityInfoAccess.getId());
if (obj == null) {
return null;
}
ASN1Sequence AccessDescriptions = (ASN1Sequence) obj;
for (int i = 0; i < AccessDescriptions.size(); i++) {
ASN1Sequence AccessDescription = (ASN1Sequence) AccessDescriptions.getObjectAt(i);
if ( AccessDescription.size() != 2 ) {
continue;
}
else if (AccessDescription.getObjectAt(0) instanceof ASN1ObjectIdentifier) {
ASN1ObjectIdentifier id = (ASN1ObjectIdentifier)AccessDescription.getObjectAt(0);
if ("1.3.6.1.5.5.7.48.2".equals(id.getId())) {
ASN1Primitive description = (ASN1Primitive)AccessDescription.getObjectAt(1);
String AccessLocation = getStringFromGeneralName(description);
if (AccessLocation == null) {
return "" ;
}
else {
return AccessLocation ;
}
}
}
}
} catch (IOException e) {
return null;
}
return null;
}
static ASN1Primitive getExtensionValue(X509Certificate certificate, String oid) throws IOException {
byte[] bytes = certificate.getExtensionValue(oid);
if (bytes == null) {
return null;
}
ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(bytes));
ASN1OctetString octs = (ASN1OctetString) aIn.readObject();
aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets()));
return aIn.readObject();
}
static String getStringFromGeneralName(ASN1Primitive names) throws IOException {
ASN1TaggedObject taggedObject = (ASN1TaggedObject) names ;
return new String(ASN1OctetString.getInstance(taggedObject, false).getOctets(), "ISO-8859-1");
}
//
// inner class
//
static class ValidationData {
final List<byte[]> crls = new ArrayList<byte[]>();
final List<byte[]> ocsps = new ArrayList<byte[]>();
final List<byte[]> certs = new ArrayList<byte[]>();
}
//
// member variables
//
final PdfDocument pdfDocument;
final Map<PdfName,ValidationData> validated = new HashMap<PdfName,ValidationData>();
}
(AdobeLtvEnabling.java)
Example use
You can use the AdobeLtvEnabling class like this:
try ( PdfReader pdfReader = new PdfReader(SOURCE);
PdfWriter pdfWriter = new PdfWriter(TARGET);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter,
new StampingProperties().preserveEncryption().useAppendMode())) {
AdobeLtvEnabling adobeLtvEnabling = new AdobeLtvEnabling(pdfDocument);
IOcspClient ocsp = new OcspClientBouncyCastle(null);
ICrlClient crl = new CrlClientOnline();
adobeLtvEnabling.enable(ocsp, crl);
}
(MakeLtvEnabled test testLtvEnableSignWithoutLtv)
Limitations
As this code essentially is ported from the iText 5 code from the referenced answer, it also inherits the limitations listed in that answer:
The code works under some simplifying restrictions, in particular:
signature time stamps are ignored,
retrieved CRLs are assumed to be direct and complete,
the complete certificate chains are assumed to be buildable using AIA entries.
You can improve the code accordingly if these restrictions are not acceptable for you.

Code works fine on JAVA But Fails to Create Decrypted File on Android

I was trying to make a file File Locker App for Android. For encryption & Decryption I used some code which I previously tested on JAVA. It works fine on JAVA, But Fails to Create The Decrypted File on Android platform.
My Code is something like bellow,
public class Cryptographer {
private static final String ALGORITHM = "AES";
private final static String ALGO_RANDOM_NUM_GENERATOR = "SHA1PRNG";
public static int encrypt(String key, File inputFile, File outputFile)
throws CryptographyException {
if(!outputFile.getParentFile().exists())outputFile.getParentFile().mkdir();
return StartCryptography(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
}
public static int decrypt(String key, File inputFile, File outputFile)
throws CryptographyException {
if(!outputFile.getParentFile().exists())outputFile.getParentFile().mkdir();
return StartCryptography(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
}
private static int StartCryptography(int cipherMode, String key, File inputFile,
File outputFile) throws CryptographyException {
int performance = -1;
try {
SecureRandom random = SecureRandom.getInstance(ALGO_RANDOM_NUM_GENERATOR);
random.setSeed(key.getBytes());
KeyGenerator generator = KeyGenerator.getInstance(ALGORITHM);
generator.init(random);
SecretKey key1 = generator.generateKey();
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(cipherMode, key1);
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
performance = 1;
} catch (NoSuchPaddingException | NoSuchAlgorithmException
| InvalidKeyException | BadPaddingException
| IllegalBlockSizeException | IOException ex) {
throw new CryptographyException("Error encrypting/decrypting file", ex);
} finally {
return performance;
}
}
}
I am using a button which when pressed All Files From a declared Array Should First be encrypted, and then the encrypted file will be decrypted to another location. But no Decrypted file is created.
My onClick Method of the button looks like bellow,
public void onKeyDown1(View view) throws CryptographyException {
File outfile = new File(ExternalStorageDirectoryPath, "Encrypted");
File outfileDec = new File(ExternalStorageDirectoryPath, "Decrypted");
for (MyFiles f : files) {
if (f.getCheckstate()) {
File EncFile=new File(outfile,f.getName());
//File DecFile=new File(outfileDec,f.getName());
Cryptographer.encrypt(key, f, EncFile);
Cryptographer.decrypt(key, EncFile, DecFile);
}
}
}
Someone please help me..!!
The ExternalStorageDirectoryPathis a String retrieved by Calling Environment.getExternalStorageDirectory().getAbsolutePath(); .
And MyFiles Class is
public class MyFiles extends File {
boolean Checkstate=false;
public MyFiles(File dir, String name) {
super(dir, name);
}
public MyFiles(String path) {
super(path);
}
public MyFiles(String dirPath, String name) {
super(dirPath, name);
}
public MyFiles(URI uri) {
super(uri);
}
public void setCheckstate(boolean checkstate) {
Checkstate = checkstate;
}
public boolean getCheckstate(){
return Checkstate;
}
public MyFiles[] listFiles(FileFilter filter) {
MyFiles[] files = listFiles();
if (filter == null || files == null) {
return files;
}
List<MyFiles> result = new ArrayList<MyFiles>(files.length);
for (MyFiles file : files) {
if (filter.accept(file)) {
result.add(file);
}
}
return result.toArray(new MyFiles[result.size()]);
}
public MyFiles[] listFiles() {
return filenamesToFiles(list());
}
private MyFiles[] filenamesToFiles(String[] filenames) {
if (filenames == null) {
return null;
}
int count = filenames.length;
MyFiles[] result = new MyFiles[count];
for (int i = 0; i < count; ++i) {
result[i] = new MyFiles(this, filenames[i]);
}
return result;
}
}
I suppose it might be lack of permissions in Manifest file of your android app. Check: http://developer.android.com/guide/topics/manifest/manifest-intro.html
Or you are trying to write in a location your app is not allowed

Hashing a .raw file shows NullPointerException in Java

I want to hash a file in Java by calling a file that ends with .raw. These are the codes I used:
FileSearch.java
public class FileSearch
{
private static final File file = null;
public static File findfile(File file) throws IOException
{
String drive = (new DetectDrive()).USBDetect();
Path start = FileSystems.getDefault().getPath(drive);
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
{
if (file.toString().endsWith(".raw"))
{
System.out.println(file);
}
return FileVisitResult.CONTINUE;
}
});
return file;
}
public static void main(String[] args) throws Exception
{
Hash hasher = new Hash();
FileSearch.findfile(file);
try
{
if (file.toString().endsWith("raw"))
{
hasher.hash(file);
}
} catch (IOException e)
{
e.printStackTrace();
}
}
}
Hash.java
public class Hash
{
public void hash(File file) throws Exception
{
MessageDigest md = MessageDigest.getInstance("MD5");
FileInputStream fis = new FileInputStream(file);
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = fis.read(dataBytes)) != -1)
{
md.update(dataBytes, 0, nread);
};
byte[] mdbytes = md.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < mdbytes.length; i++)
{
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("Digest(in hex format):: " + sb.toString());
}
}
The first code is used to find the file and perform hash by running the main method and the second code is the method for hashing the file (by MD5). However, when I run the it gives an ouput:
"name of raw file"
Exception in thread "main" java.lang.NullPointerException at FileSearch.main(FileSearch.java:33)
line 33 is the if (file.toString().endsWith("raw")) portion. Anyone knows how I can fix this?
You never initalize file with anything (Well, you initalize it with null)
private static final File file = null;
So when you call
if (file.toString().endsWith("raw"))
file can only be null.
What you probably want is just
file = FileSearch.findfile(file);
See:
What is a NullPointerException, and how do I fix it?

Categories