diff --git a/pg/src/main/java/org/bouncycastle/openpgp/api/OpenPGPCertificate.java b/pg/src/main/java/org/bouncycastle/openpgp/api/OpenPGPCertificate.java index 267cfd72ce..52f848973a 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/api/OpenPGPCertificate.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/api/OpenPGPCertificate.java @@ -219,9 +219,9 @@ public Map getSubkeys() *
      * keys = getComponentKeysWithFlag(date, KeyFlags.ENCRYPT_COMMS, KeyFlags.ENCRYPT_STORAGE);
      * 
- * If you instead want to access all keys, that have BOTH flags, you need to
&
both flags: + * If you instead want to access all keys, that have BOTH flags, you need to
|
both flags: *
-     * keys = getComponentKeysWithFlag(date, KeyFlags.ENCRYPT_COMMS & KeyFlags.ENCRYPT_STORAGE);
+     * keys = getComponentKeysWithFlag(date, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE);
      * 
* * @param evaluationTime reference time @@ -906,15 +906,34 @@ public List getEncryptionKeys() * @return encryption keys */ public List getEncryptionKeys(Date evaluationTime) + { + return getEncryptionKeys(evaluationTime, KeyFlags.ENCRYPT_COMMS, KeyFlags.ENCRYPT_STORAGE); + } + + /** + * Return a list of all keys that are - at evaluation time - valid encryption keys and carry any of the given + * key flags. + * + * Note: To get all keys that have EITHER flag A or B, call
getEncryptionKeys(evalTime, A, B)
. + * To instead get all keys that have BOTH flags A AND B, call
getEncryptionKeys(evalTime, A | B)
. + * + * @see KeyFlags + * + * @param evaluationTime evaluation time + * @param keyFlags key flags + * @return keys with the given flags + */ + public List getEncryptionKeys(Date evaluationTime, final int... keyFlags) { return filterKeys(evaluationTime, new KeyFilter() { @Override public boolean test(OpenPGPComponentKey key, Date time) { - return key.isEncryptionKey(time); + return key.isEncryptionKey(time, keyFlags); } }); + } /** @@ -1334,7 +1353,7 @@ public KeyFlags getKeyFlags(Date evaluationTime) * Return
true
, if the key has any of the given key flags. *

* Note: To check if the key has EITHER flag A or B, call

hasKeyFlags(evalTime, A, B)
. - * To instead check, if the key has BOTH flags A AND B, call
hasKeyFlags(evalTime, A & B)
. + * To instead check, if the key has BOTH flags A AND B, call
hasKeyFlags(evalTime, A | B)
. * * @param evaluationTime evaluation time * @param flags key flags (see {@link KeyFlags} for possible values) @@ -2132,12 +2151,28 @@ public boolean isEncryptionKey() } /** - * Return true, if the is - at evaluation time - marked as an encryption key. + * Return true, if the key is - at evaluation time - marked as an encryption key. * * @param evaluationTime evaluation time * @return true if key is an encryption key at evaluation time, false otherwise */ public boolean isEncryptionKey(Date evaluationTime) + { + return isEncryptionKey(evaluationTime, KeyFlags.ENCRYPT_COMMS, KeyFlags.ENCRYPT_STORAGE); + } + + /** + * Return true, if the key is - at evaluation time - marked as an encryption key and carries any of the given + * key flags. + * + * Note: To check if the key has EITHER flag A or B, call
isEncryptionKey(evalTime, A, B)
. + * To instead check, if the key has BOTH flags A AND B, call
isEncryptionKey(evalTime, A | B)
. + * + * @param evaluationTime evaluation time + * @param keyFlags key flags + * @return true if the key is an encryption key for any of the given key flags + */ + public boolean isEncryptionKey(Date evaluationTime, int... keyFlags) { if (!rawPubkey.isEncryptionKey()) { @@ -2145,8 +2180,7 @@ public boolean isEncryptionKey(Date evaluationTime) return false; } - return hasKeyFlags(evaluationTime, KeyFlags.ENCRYPT_STORAGE) || - hasKeyFlags(evaluationTime, KeyFlags.ENCRYPT_COMMS); + return hasKeyFlags(evaluationTime, keyFlags); } /** diff --git a/pg/src/test/java/org/bouncycastle/openpgp/api/test/OpenPGPCertificateTest.java b/pg/src/test/java/org/bouncycastle/openpgp/api/test/OpenPGPCertificateTest.java index 7fbd93f5a2..f40ba849f8 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/api/test/OpenPGPCertificateTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/api/test/OpenPGPCertificateTest.java @@ -49,6 +49,7 @@ protected void performTestWith(OpenPGPApi api) testSKSignsPKRevokedNoSubpacket(api); testPKSignsPKRevocationSuperseded(api); testGetPrimaryUserId(api); + testGetEncryptionKeysForPurpose(api); } private void testOpenPGPv6Key(OpenPGPApi api) @@ -826,6 +827,49 @@ public PGPSignatureSubpacketGenerator apply(PGPSignatureSubpacketGenerator subpa key.getPrimaryUserId(oneHourAgo)); } + private void testGetEncryptionKeysForPurpose(OpenPGPApi api) + throws IOException { + + // This cert has two separate encryption subkeys: + // 7415331173EF1FEA7AB2AFC0E40DE83A8CBBE4BC is for storage + // 95EFDD6BD87C62F0FC109C2964F5A6B5F40F379D is for comms + String CERT = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" + + "Comment: 88BF 5516 C226 5B7D 1817 03E6 1FF0 DE1E AF8B 379F\n" + + "\n" + + "mCYEaVxG2BvmBuO3v5cDQQCuGnAIuaeP0frpw7mutcMQwPkGuuAKUMKSBB8bCgA+\n" + + "FqEEiL9VFsImW30YFwPmH/DeHq+LN58FgmlcRtgCngkFlQoJCAsFlgIDAQAEiwkI\n" + + "BwknCQEJAgkDCAECmwEACgkQH/DeHq+LN5/NVHbqH098dr34p9KVQQNLXr8CITqP\n" + + "vLTkijVXyfZg6Lz1krs3EgEvc8nz3evyYj5xJI+Hg1kHb+ctB5myyTyEtge4JgRp\n" + + "XEbYG52SLEi5Biq9vn1pFgrozM2QuCqkwXtOr/0ASs0b3t20wsAnBBgbCgCTFqEE\n" + + "iL9VFsImW30YFwPmH/DeHq+LN58FgmlcRtgCmwJyoAQZGwoAHRahBGp6EAtdr26T\n" + + "x4sGLa+TQ+g71BlpBYJpXEbYAAoJEK+TQ+g71BlpkJ4VPAQeTXN88wXzLloW2WYP\n" + + "5w3w7Js4csGE5OynUupCNwUBcIfC+FBMuUdgqjczw4xKRLbZMgp5YLr8Ve3pG48L\n" + + "AAoJEB/w3h6vizefXrbECKbGBPh+c3+fFG3Au0gzkRMCsZsMaQaRWlQ1E2P/VWlo\n" + + "xy4JF5nCA6bSC+sFl+DTbwpgvdQlIILR9O386EcHuCYEaVxG2Blrm96fHzaN1JmO\n" + + "uhU0OMbiDMBYKOL3Iup+TQWzx897CMJ0BBgbCgAgFqEEiL9VFsImW30YFwPmH/De\n" + + "Hq+LN58FgmlcRtgCmwQACgkQH/DeHq+LN5/wOkjl+MJktOsh+COv4tAhSu2kR0iw\n" + + "rdY4IAEp7jlnZfx0BVMnVURSrZSge3Zw2vbQQe864GA3Y4le4CWFKm2QAwG4JgRp\n" + + "XEbYGUzlbIju0H0KDcLmLXsXp7CCLmkcnSjNAj9WTRW7GCJownQEGBsKACAWoQSI\n" + + "v1UWwiZbfRgXA+Yf8N4er4s3nwWCaVxG2AKbCAAKCRAf8N4er4s3n4+EpHlXYNzD\n" + + "I2OT9NpobaalDbmDMuvIu/81Uoxv+pJLkrMV+WW5be27HrH6w7YTH1TngILr4V2e\n" + + "jSB2HhjClk4YBw==\n" + + "=3S3M\n" + + "-----END PGP PUBLIC KEY BLOCK-----"; + + OpenPGPCertificate cert = api.readKeyOrCertificate().parseCertificate(CERT); + + List allEncryptionKeys = cert.getEncryptionKeys(); + isEquals(2, allEncryptionKeys.size()); + + List storageEncKeys = cert.getEncryptionKeys(new Date(), KeyFlags.ENCRYPT_STORAGE); + isEquals(1, storageEncKeys.size()); + isEquals(new KeyIdentifier("7415331173EF1FEA7AB2AFC0E40DE83A8CBBE4BC"), storageEncKeys.get(0).getKeyIdentifier()); + + List commEncKeys = cert.getEncryptionKeys(new Date(), KeyFlags.ENCRYPT_COMMS); + isEquals(1, commEncKeys.size()); + isEquals(new KeyIdentifier("95EFDD6BD87C62F0FC109C2964F5A6B5F40F379D"), commEncKeys.get(0).getKeyIdentifier()); + } + public static class TestSignature { private final PGPSignature signature;