Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/pg
diff options
context:
space:
mode:
authorDavid Hook <dgh@cryptoworkshop.com>2014-05-04 12:16:34 +0400
committerDavid Hook <dgh@cryptoworkshop.com>2014-05-04 12:16:34 +0400
commitb510c177ed036de78315b8165a505897db77b16e (patch)
treed2327a3b90bbec2e3247108f0787047d586e4049 /pg
parent6a8950309c15bec575c3c7bd955926cc21809458 (diff)
added support for handling raw IDs for dealing with key rings without UTF8 encoded IDs.
Diffstat (limited to 'pg')
-rw-r--r--pg/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java30
-rw-r--r--pg/src/main/java/org/bouncycastle/openpgp/PGPKeyRing.java2
-rw-r--r--pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java97
-rw-r--r--pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java6
-rw-r--r--pg/src/main/java/org/bouncycastle/openpgp/PGPSignature.java31
-rw-r--r--pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPPublicKeyRing.java26
-rw-r--r--pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPSecretKeyRing.java27
-rw-r--r--pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPPublicKeyRing.java26
-rw-r--r--pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPSecretKeyRing.java27
-rw-r--r--pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java59
10 files changed, 311 insertions, 20 deletions
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java
index 15ae71b1..7fd79186 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java
@@ -2,6 +2,7 @@ package org.bouncycastle.bcpg;
import java.io.IOException;
+import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Strings;
/**
@@ -24,12 +25,37 @@ public class UserIDPacket
{
this.idData = Strings.toUTF8ByteArray(id);
}
-
+
+ public UserIDPacket(byte[] rawID)
+ {
+ this.idData = Arrays.clone(rawID);
+ }
+
public String getID()
{
return Strings.fromUTF8ByteArray(idData);
}
-
+
+ public byte[] getRawID()
+ {
+ return Arrays.clone(idData);
+ }
+
+ public boolean equals(Object o)
+ {
+ if (o instanceof UserIDPacket)
+ {
+ return Arrays.areEqual(this.idData, ((UserIDPacket)o).idData);
+ }
+
+ return false;
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(this.idData);
+ }
+
public void encode(
BCPGOutputStream out)
throws IOException
diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPKeyRing.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPKeyRing.java
index e12da58c..413e1af9 100644
--- a/pg/src/main/java/org/bouncycastle/openpgp/PGPKeyRing.java
+++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPKeyRing.java
@@ -79,7 +79,7 @@ public abstract class PGPKeyRing
if (obj instanceof UserIDPacket)
{
UserIDPacket id = (UserIDPacket)obj;
- ids.add(id.getID());
+ ids.add(id);
}
else
{
diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java
index a8b6692b..11b96ac1 100644
--- a/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java
+++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java
@@ -365,7 +365,7 @@ public class PGPPublicKey
/**
* Return the strength of the key in bits.
*
- * @return bit strenght of key.
+ * @return bit strength of key.
*/
public int getBitStrength()
{
@@ -383,15 +383,36 @@ public class PGPPublicKey
for (int i = 0; i != ids.size(); i++)
{
- if (ids.get(i) instanceof String)
+ if (ids.get(i) instanceof UserIDPacket)
{
- temp.add(ids.get(i));
+ temp.add(((UserIDPacket)ids.get(i)).getID());
}
}
return temp.iterator();
}
-
+
+ /**
+ * Return any userIDs associated with the key in raw byte form. No attempt is made
+ * to convert the IDs into Strings.
+ *
+ * @return an iterator of Strings.
+ */
+ public Iterator getRawUserIDs()
+ {
+ List temp = new ArrayList();
+
+ for (int i = 0; i != ids.size(); i++)
+ {
+ if (ids.get(i) instanceof UserIDPacket)
+ {
+ temp.add(((UserIDPacket)ids.get(i)).getRawID());
+ }
+ }
+
+ return temp.iterator();
+ }
+
/**
* Return any user attribute vectors associated with the key.
*
@@ -421,6 +442,24 @@ public class PGPPublicKey
public Iterator getSignaturesForID(
String id)
{
+ return getSignaturesForID(new UserIDPacket(id));
+ }
+
+ /**
+ * Return any signatures associated with the passed in id.
+ *
+ * @param rawID the id to be matched in raw byte form.
+ * @return an iterator of PGPSignature objects.
+ */
+ public Iterator getSignaturesForID(
+ byte[] rawID)
+ {
+ return getSignaturesForID(new UserIDPacket(rawID));
+ }
+
+ private Iterator getSignaturesForID(
+ UserIDPacket id)
+ {
for (int i = 0; i != ids.size(); i++)
{
if (id.equals(ids.get(i)))
@@ -428,10 +467,10 @@ public class PGPPublicKey
return ((ArrayList)idSigs.get(i)).iterator();
}
}
-
+
return null;
}
-
+
/**
* Return an iterator of signatures associated with the passed in user attributes.
*
@@ -548,11 +587,11 @@ public class PGPPublicKey
for (int i = 0; i != ids.size(); i++)
{
- if (ids.get(i) instanceof String)
+ if (ids.get(i) instanceof UserIDPacket)
{
- String id = (String)ids.get(i);
+ UserIDPacket id = (UserIDPacket)ids.get(i);
- out.writePacket(new UserIDPacket(id));
+ out.writePacket(id);
}
else
{
@@ -630,7 +669,7 @@ public class PGPPublicKey
String id,
PGPSignature certification)
{
- return addCert(key, id, certification);
+ return addCert(key, new UserIDPacket(id), certification);
}
/**
@@ -708,7 +747,21 @@ public class PGPPublicKey
PGPPublicKey key,
String id)
{
- return removeCert(key, id);
+ return removeCert(key, new UserIDPacket(id));
+ }
+
+ /**
+ * Remove any certifications associated with a given id on a key.
+ *
+ * @param key the key the certifications are to be removed from.
+ * @param rawID the id that is to be removed in raw byte form.
+ * @return the re-certified key, null if the id was not found on the key.
+ */
+ public static PGPPublicKey removeCertification(
+ PGPPublicKey key,
+ byte[] rawID)
+ {
+ return removeCert(key, new UserIDPacket(rawID));
}
private static PGPPublicKey removeCert(
@@ -739,6 +792,22 @@ public class PGPPublicKey
/**
* Remove a certification associated with a given id on a key.
+ *
+ * @param key the key the certifications are to be removed from.
+ * @param id the id that the certification is to be removed from (in its raw byte form)
+ * @param certification the certification to be removed.
+ * @return the re-certified key, null if the certification was not found.
+ */
+ public static PGPPublicKey removeCertification(
+ PGPPublicKey key,
+ byte[] id,
+ PGPSignature certification)
+ {
+ return removeCert(key, new UserIDPacket(id), certification);
+ }
+
+ /**
+ * Remove a certification associated with a given id on a key.
*
* @param key the key the certifications are to be removed from.
* @param id the id that the certification is to be removed from.
@@ -750,7 +819,7 @@ public class PGPPublicKey
String id,
PGPSignature certification)
{
- return removeCert(key, id, certification);
+ return removeCert(key, new UserIDPacket(id), certification);
}
/**
@@ -860,13 +929,13 @@ public class PGPPublicKey
{
for (Iterator it = key.getUserIDs(); it.hasNext();)
{
- String id = (String)it.next();
+ UserIDPacket id = (UserIDPacket)it.next();
for (Iterator sIt = key.getSignaturesForID(id); sIt.hasNext();)
{
if (certification == sIt.next())
{
found = true;
- returnKey = PGPPublicKey.removeCertification(returnKey, id, certification);
+ returnKey = PGPPublicKey.removeCertification(returnKey, id.getRawID(), certification);
}
}
}
diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java
index 7d1a9e38..bd0931df 100644
--- a/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java
+++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java
@@ -520,11 +520,11 @@ public class PGPSecretKey
for (int i = 0; i != pub.ids.size(); i++)
{
- if (pub.ids.get(i) instanceof String)
+ if (pub.ids.get(i) instanceof UserIDPacket)
{
- String id = (String)pub.ids.get(i);
+ UserIDPacket id = (UserIDPacket)pub.ids.get(i);
- out.writePacket(new UserIDPacket(id));
+ out.writePacket(id);
}
else
{
diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPSignature.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPSignature.java
index 4bd7ea0a..77597049 100644
--- a/pg/src/main/java/org/bouncycastle/openpgp/PGPSignature.java
+++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPSignature.java
@@ -311,6 +311,37 @@ public class PGPSignature
}
/**
+ * Verify the signature as certifying the passed in public key as associated
+ * with the passed in rawID.
+ *
+ * @param rawID id the key was stored under in its raw byte form.
+ * @param key the key to be verified.
+ * @return true if the signature matches, false otherwise.
+ * @throws PGPException
+ */
+ public boolean verifyCertification(
+ byte[] rawID,
+ PGPPublicKey key)
+ throws PGPException
+ {
+ if (verifier == null)
+ {
+ throw new PGPException("PGPSignature not initialised - call init().");
+ }
+
+ updateWithPublicKey(key);
+
+ //
+ // hash in the rawID
+ //
+ updateWithIdData(0xb4, rawID);
+
+ addTrailer();
+
+ return verifier.verify(this.getSignature());
+ }
+
+ /**
* Verify a certification for the passed in key against the passed in
* master key.
*
diff --git a/pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPPublicKeyRing.java b/pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPPublicKeyRing.java
new file mode 100644
index 00000000..4023be76
--- /dev/null
+++ b/pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPPublicKeyRing.java
@@ -0,0 +1,26 @@
+package org.bouncycastle.openpgp.bc;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.bouncycastle.openpgp.PGPPublicKeyRing;
+import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
+import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
+
+public class BcPGPPublicKeyRing
+ extends PGPPublicKeyRing
+{
+ private static KeyFingerPrintCalculator fingerPrintCalculator = new BcKeyFingerprintCalculator();
+
+ public BcPGPPublicKeyRing(byte[] encoding)
+ throws IOException
+ {
+ super(encoding, fingerPrintCalculator);
+ }
+
+ public BcPGPPublicKeyRing(InputStream in)
+ throws IOException
+ {
+ super(in, fingerPrintCalculator);
+ }
+}
diff --git a/pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPSecretKeyRing.java b/pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPSecretKeyRing.java
new file mode 100644
index 00000000..8dac1d5e
--- /dev/null
+++ b/pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPSecretKeyRing.java
@@ -0,0 +1,27 @@
+package org.bouncycastle.openpgp.bc;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPSecretKeyRing;
+import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
+import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
+
+public class BcPGPSecretKeyRing
+ extends PGPSecretKeyRing
+{
+ private static KeyFingerPrintCalculator fingerPrintCalculator = new BcKeyFingerprintCalculator();
+
+ public BcPGPSecretKeyRing(byte[] encoding)
+ throws IOException, PGPException
+ {
+ super(encoding, fingerPrintCalculator);
+ }
+
+ public BcPGPSecretKeyRing(InputStream in)
+ throws IOException, PGPException
+ {
+ super(in, fingerPrintCalculator);
+ }
+}
diff --git a/pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPPublicKeyRing.java b/pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPPublicKeyRing.java
new file mode 100644
index 00000000..b2281d28
--- /dev/null
+++ b/pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPPublicKeyRing.java
@@ -0,0 +1,26 @@
+package org.bouncycastle.openpgp.jcajce;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.bouncycastle.openpgp.PGPPublicKeyRing;
+import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
+import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
+
+public class JcaPGPPublicKeyRing
+ extends PGPPublicKeyRing
+{
+ private static KeyFingerPrintCalculator fingerPrintCalculator = new JcaKeyFingerprintCalculator();
+
+ public JcaPGPPublicKeyRing(byte[] encoding)
+ throws IOException
+ {
+ super(encoding, fingerPrintCalculator);
+ }
+
+ public JcaPGPPublicKeyRing(InputStream in)
+ throws IOException
+ {
+ super(in, fingerPrintCalculator);
+ }
+}
diff --git a/pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPSecretKeyRing.java b/pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPSecretKeyRing.java
new file mode 100644
index 00000000..735d4e57
--- /dev/null
+++ b/pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPSecretKeyRing.java
@@ -0,0 +1,27 @@
+package org.bouncycastle.openpgp.jcajce;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPSecretKeyRing;
+import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
+import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
+
+public class JcaPGPSecretKeyRing
+ extends PGPSecretKeyRing
+{
+ private static KeyFingerPrintCalculator fingerPrintCalculator = new JcaKeyFingerprintCalculator();
+
+ public JcaPGPSecretKeyRing(byte[] encoding)
+ throws IOException, PGPException
+ {
+ super(encoding, fingerPrintCalculator);
+ }
+
+ public JcaPGPSecretKeyRing(InputStream in)
+ throws IOException, PGPException
+ {
+ super(in, fingerPrintCalculator);
+ }
+}
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 3b3dfde8..e78026d4 100644
--- a/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java
+++ b/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java
@@ -24,6 +24,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.openpgp.jcajce.JcaPGPPublicKeyRing;
import org.bouncycastle.openpgp.jcajce.JcaPGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.jcajce.JcaPGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
@@ -35,6 +36,7 @@ import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBu
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
+import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.SimpleTest;
@@ -1166,6 +1168,31 @@ public class PGPKeyRingTest
"tXV/Z3H/Ot4u3E7H+6fHPElFYbQUdGVzdCA8dGVzdEBrZXkudGVzdD4="
);
+ private static final byte[] problemUserID = Base64.decode(
+ "mQGiBDfzC2IRBADjnqYxAM1LPqFZCpF9ULb4G7L88E/p4sNo4k1LkzGtNOiroEHcacEAcTeP" +
+ "ljhgTA06l9jpnwx/dE0MEAiEtYexvkBv3LR2qXvuF67TKKlvanB32g0AmxNijHDdN2d+79ZA" +
+ "heZ4rY702W6DZh6FuKMAsTBfAFW5jLCWyJ4FwsLILwCg/3mjYePND5l0UcxaV0RKRBGnhqsE" +
+ "AIb9PJyWxSa8uzYQ+/APMg16Rrbti21zEQorFoc6yrC2hWbS7ro5yEVJxJa14s7VKlR+IAhg" +
+ "vR2+Q6jF6uvE1NZXzX6bvGaK3IpWMZdYcUY63EsHnutV+xON6Xd9C06xjAssvRQnxSuLXCg4" +
+ "md1Cr2kiKWaBExzxniKeql5lrqXKBACPcHbwZ8Efgt1TLG4yUf8nIQZwDeAhUPqJVWXurpWx" +
+ "r36ET4oQWb5HhO9GEe+2dttyJgV+stZJbZrPVmxmY1hUTZxIZ1ygGcMvrsVZZO0C9QsvMCyy" +
+ "xx4RzmTqomkC6Gtl3KtrZ4X28FQFDZi7MQaSXKEu2yS/NKJu2iT2BNKnE7QjTGFzc2UgTb5y" +
+ "a2VkYWhsIExhcnNlbiA8bG1sQGdyMy5kaz6ISwQQEQIACwUCN/MLYgQLAwIBAAoJEKg2SsWJ" +
+ "xEiGFbcAnA/ka/KE0Mnli7ybUhSrbESR/fZlAJ9SxU2foiRHMF8pF7I8KIJ9AQKSZLkCDQQ3" +
+ "8wtiEAgA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt" +
+ "90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/" +
+ "Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4DUUdD3yIsxx8" +
+ "Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaG" +
+ "xAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwACAgf/cugy" +
+ "0nyWpA6GxoNqpdky1oCEbgII/lFKkGfQb/sHLgHURjmiaDXSuRJDRXC6YVC0HWqA+bfknR5m" +
+ "o1cvohu4GL/oul1eD85UfU29vg5Hr6f601o6xWVCiHF14B24JvO7jhYMd1MQRl7PVzH0a1Gp" +
+ "4hSoEvsUjU1HhGUhmMpUxwGJyIFt4RTkqKWK15omuJf4TLT47T58n9uClTNyxpx+oJGaiD0O" +
+ "SiEn9d4w5XFewhyXFQhisr99979dLq+buvH1QueMkVDExF4D8LN5gid8JPy/RqFxnHE8AcSF" +
+ "XHz9ou8m936pkyKYIMQkCwdw7/Wv7MK64ZED2zOnXnSb/JWY2YhGBBgRAgAGBQI38wtiAAoJ" +
+ "EKg2SsWJxEiGJdcAoIQOLuHGGS01Gz5WUpiQZYRtRMIYAKDuYx6bfQngRMs3/gEG0zoSGohY" +
+ "lQ=="
+ );
+
public void test1()
throws Exception
{
@@ -2624,6 +2651,37 @@ public class PGPKeyRingTest
}
}
+ // test for key ring with non-UTF8 User ID.
+ private void testBadUserID()
+ throws Exception
+ {
+ PGPPublicKeyRing pgpRing = new JcaPGPPublicKeyRing(problemUserID);
+
+ byte[] enc = pgpRing.getEncoded();
+
+ if (!Arrays.areEqual(problemUserID, enc))
+ {
+ fail("encoded key does not match original");
+ }
+
+ PGPPublicKey pubKey = pgpRing.getPublicKey();
+
+ Iterator it = pubKey.getRawUserIDs();
+
+ byte[] rawID = (byte[])it.next();
+
+ it = pubKey.getSignaturesForID(rawID);
+
+ PGPSignature sig = (PGPSignature)it.next();
+
+ sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), pubKey);
+
+ if (!sig.verifyCertification(rawID, pubKey))
+ {
+ fail("Certification not validated for rawID");
+ }
+ }
+
public void performTest()
throws Exception
{
@@ -2649,6 +2707,7 @@ public class PGPKeyRingTest
testSecretKeyRingWithPersonalCertificate();
insertMasterTest();
testUmlaut();
+ testBadUserID();
}
catch (PGPException e)
{