Need help: removing a signature from a public key

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Need help: removing a signature from a public key

Lou Wynn

Hi,

I've attached a piece of code that removes signatures from a public key. It throws the following exception with
bcpg-jdk15on-156:

Exception in thread "main" java.lang.ClassCastException: [B cannot be cast to org.bouncycastle.bcpg.UserIDPacket
    at org.bouncycastle.openpgp.PGPPublicKey.removeCertification(PGPPublicKey.java:1051)
    at SignatureRemover.main(SignatureRemover.java:79)

When I traced the code, I noticed that the getRawUserIDs() function should return UserIDPacket because the function checks the type before taking a returned value. Therefore I have no idea why this can happen. Is it possible that my certification code causes the problem? My certification code looks like the following:

    PGPSignatureGenerator sigGen = getSignatureGenerator(pub);
    sigGen.init(type, signKey);
    PGPSignatureSubpacketGenerator subpGen = new PGPSignatureSubpacketGenerator();
    subpGen.setSignerUserID(false, signerId);
    subpGen.setIssuerKeyID(true, signKey.getKeyID());
    subpGen.setPrimaryUserID(true, true);
    subpGen.setSignatureCreationTime(true, new Date());
    subpGen.setSignatureExpirationTime(true, certExpiry);
    PGPSignatureSubpacketVector hashedPacks = subpGen.generate();
    sigGen.setHashedSubpackets(hashedPacks);
    PGPSignature cert = sigGen.generateCertification(userID, pub);
    pub = PGPPublicKey.addCertification(pub, userID, cert);
-- 
Thanks,
Lou

SignatureRemover.java (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Need help: removing a signature from a public key

Lou Wynn

After a careful trace of the program, I've found a bug in the getRawUserIDs() function. I overlooked the type casting position. It wasn't on the object added into the return value. I've made the git diff for it, and here's it:

diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java
index 6ef2e26..9a897bd 100644
--- a/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java
+++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java
@@ -423,7 +423,7 @@ public Iterator getRawUserIDs()
         {
             if (ids.get(i) instanceof UserIDPacket)
             {
-                temp.add(((UserIDPacket)ids.get(i)).getRawID());
+                temp.add((UserIDPacket)ids.get(i));
             }
         }
 
diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java
index e0aaf60..7dc6a7f 100644
--- a/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java
+++ b/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java
@@ -17,6 +17,7 @@
 import org.bouncycastle.bcpg.SecretKeyPacket;
 import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
 import org.bouncycastle.bcpg.TrustPacket;
+import org.bouncycastle.bcpg.UserIDPacket;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.jce.spec.ElGamalParameterSpec;
 import org.bouncycastle.openpgp.PGPEncryptedData;
@@ -2751,7 +2752,7 @@ private void testBadUserID()
 
         Iterator it = pubKey.getRawUserIDs();
 
-        byte[] rawID = (byte[])it.next();
+        byte[] rawID = ((UserIDPacket)it.next()).getRawID();
 
         it = pubKey.getSignaturesForID(rawID);


Thanks,
Lou
On 01/03/2018 11:49 PM, Lou Wynn wrote:

Hi,

I've attached a piece of code that removes signatures from a public key. It throws the following exception with
bcpg-jdk15on-156:

Exception in thread "main" java.lang.ClassCastException: [B cannot be cast to org.bouncycastle.bcpg.UserIDPacket
    at org.bouncycastle.openpgp.PGPPublicKey.removeCertification(PGPPublicKey.java:1051)
    at SignatureRemover.main(SignatureRemover.java:79)

When I traced the code, I noticed that the getRawUserIDs() function should return UserIDPacket because the function checks the type before taking a returned value. Therefore I have no idea why this can happen. Is it possible that my certification code causes the problem? My certification code looks like the following:

    PGPSignatureGenerator sigGen = getSignatureGenerator(pub);
    sigGen.init(type, signKey);
    PGPSignatureSubpacketGenerator subpGen = new PGPSignatureSubpacketGenerator();
    subpGen.setSignerUserID(false, signerId);
    subpGen.setIssuerKeyID(true, signKey.getKeyID());
    subpGen.setPrimaryUserID(true, true);
    subpGen.setSignatureCreationTime(true, new Date());
    subpGen.setSignatureExpirationTime(true, certExpiry);
    PGPSignatureSubpacketVector hashedPacks = subpGen.generate();
    sigGen.setHashedSubpackets(hashedPacks);
    PGPSignature cert = sigGen.generateCertification(userID, pub);
    pub = PGPPublicKey.addCertification(pub, userID, cert);
-- 
Thanks,
Lou

Reply | Threaded
Open this post in threaded view
|

Re: Need help: removing a signature from a public key

David Hook-3

Hi Lou,

I think if you try your program with a more recent version of BC you will find it works. I think the issue you have is listed as fixed in the release notes for BC 1.57.

Regards,

David

On 08/01/18 10:15, Lou Wynn wrote:

After a careful trace of the program, I've found a bug in the getRawUserIDs() function. I overlooked the type casting position. It wasn't on the object added into the return value. I've made the git diff for it, and here's it:

diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java
index 6ef2e26..9a897bd 100644
--- a/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java
+++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java
@@ -423,7 +423,7 @@ public Iterator getRawUserIDs()
         {
             if (ids.get(i) instanceof UserIDPacket)
             {
-                temp.add(((UserIDPacket)ids.get(i)).getRawID());
+                temp.add((UserIDPacket)ids.get(i));
             }
         }
 
diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java
index e0aaf60..7dc6a7f 100644
--- a/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java
+++ b/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java
@@ -17,6 +17,7 @@
 import org.bouncycastle.bcpg.SecretKeyPacket;
 import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
 import org.bouncycastle.bcpg.TrustPacket;
+import org.bouncycastle.bcpg.UserIDPacket;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.jce.spec.ElGamalParameterSpec;
 import org.bouncycastle.openpgp.PGPEncryptedData;
@@ -2751,7 +2752,7 @@ private void testBadUserID()
 
         Iterator it = pubKey.getRawUserIDs();
 
-        byte[] rawID = (byte[])it.next();
+        byte[] rawID = ((UserIDPacket)it.next()).getRawID();
 
         it = pubKey.getSignaturesForID(rawID);


Thanks,
Lou
On 01/03/2018 11:49 PM, Lou Wynn wrote:

Hi,

I've attached a piece of code that removes signatures from a public key. It throws the following exception with
bcpg-jdk15on-156:

Exception in thread "main" java.lang.ClassCastException: [B cannot be cast to org.bouncycastle.bcpg.UserIDPacket
    at org.bouncycastle.openpgp.PGPPublicKey.removeCertification(PGPPublicKey.java:1051)
    at SignatureRemover.main(SignatureRemover.java:79)

When I traced the code, I noticed that the getRawUserIDs() function should return UserIDPacket because the function checks the type before taking a returned value. Therefore I have no idea why this can happen. Is it possible that my certification code causes the problem? My certification code looks like the following:

    PGPSignatureGenerator sigGen = getSignatureGenerator(pub);
    sigGen.init(type, signKey);
    PGPSignatureSubpacketGenerator subpGen = new PGPSignatureSubpacketGenerator();
    subpGen.setSignerUserID(false, signerId);
    subpGen.setIssuerKeyID(true, signKey.getKeyID());
    subpGen.setPrimaryUserID(true, true);
    subpGen.setSignatureCreationTime(true, new Date());
    subpGen.setSignatureExpirationTime(true, certExpiry);
    PGPSignatureSubpacketVector hashedPacks = subpGen.generate();
    sigGen.setHashedSubpackets(hashedPacks);
    PGPSignature cert = sigGen.generateCertification(userID, pub);
    pub = PGPPublicKey.addCertification(pub, userID, cert);
-- 
Thanks,
Lou