My requirement:
- Hash Algorithm during signing: SHA256
- Sender signs the encrypted message using its private key
- Receiver verifies the signature using Sender’s public key
I am having the below exception while verifying the signature:
Exception in thread “main” java.io.IOException: invalid header encountered
at org.bouncycastle.bcpg.BCPGInputStream.readPacket(Unknown Source)
at org.bouncycastle.openpgp.PGPLiteralData.(Unknown Source)
at org.bouncycastle.openpgp.PGPObjectFactory.nextObject(Unknown Source)
at com.groupId.auth.PGPExample.verify(PGPExample.java:253)
at com.groupId.auth.PGPExample.main(PGPExample.java:52)
The above exception is on line -> "while ((obj = pgpObjectFactory.nextObject()) != null) {..." when I click on 'PGPExample.java:253', my cursor goes to 'pgpObjectFactory.'
I am signing the message using the below code snippet:
private static byte[] sign(String message) throws IOException, PGPException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStream signedOut = new ArmoredOutputStream(out);
// Sign the message using sender's private key
PGPSecretKey senderPrivateKey = PGPUtils.getSenderPrivateKey();
BCPGOutputStream bOut = new BCPGOutputStream(signedOut);
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
new JcaPGPContentSignerBuilder(senderPrivateKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA256)
.setProvider("BC")
);
String password = "password";
signatureGenerator.init(PGPSignature.BINARY_DOCUMENT,
senderPrivateKey.extractPrivateKey(
new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(password.toCharArray())));
Iterator<?> it = senderPrivateKey.getPublicKey().getUserIDs();
if (it.hasNext()) {
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.addSignerUserID(false, (String) it.next());
signatureGenerator.setHashedSubpackets(spGen.generate());
}
InputStream in = PGPUtil.getDecoderStream(new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)));
byte[] buf = new byte[8192];
int len;
while ((len = in.read(buf)) > 0) {
signatureGenerator.update(buf, 0, len);
}
in.close();
// Generate the signature
signatureGenerator.generate().encode(bOut);
bOut.flush();
// Close streams
bOut.close();
signedOut.close();
return out.toByteArray();
}
I am verifying the signature using the below code snippet:
private static boolean verify(String message, byte[] signature) throws IOException, PGPException {
ByteArrayInputStream in = new ByteArrayInputStream(signature);
PGPObjectFactory pgpObjectFactory = new PGPObjectFactory(in, new JcaKeyFingerprintCalculator());
Object obj;
while ((obj = pgpObjectFactory.nextObject()) != null) {
if (obj instanceof PGPSignatureList) {
PGPSignatureList signatureList = (PGPSignatureList) obj;
if (signatureList.isEmpty()) {
throw new IllegalArgumentException("No signature found in the data");
}
PGPSignature pgpSignature = signatureList.get(0);
pgpSignature.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), PGPUtils.getReceiverPublicKey());
pgpSignature.update(message.getBytes(StandardCharsets.UTF_8));
return pgpSignature.verify();
}
}
throw new IllegalArgumentException("No signature found in the data");
}
My main method call:
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
byte[] signature = sign(message);
System.out.println("Signature: ");
System.out.println(new String(signature));
boolean verified = verify(message, signature);
System.out.println("Signature Verified: " + verified);
}
Below is my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.8</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.groupId</groupId>
<artifactId>auth</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>auth</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk18on</artifactId>
<version>1.77</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.16.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
I tried hard to resolve this issue but couldn’t find the solution, kindly give me suggestions or solution for this.
I want to sign my message & then I tried to verify it but when I use the above code snippets I have provided I am not getting verified successfully or true result instead I am having this exception “invalid header encountered”.
Kindly provide me the solution for it, as it is too much urgent for me to resolve it by today.
Thanks in advance! ????
MM Ary is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.