11package org .bouncycastle .openpgp .test ;
22
33import java .io .ByteArrayInputStream ;
4+ import java .io .IOException ;
5+ import java .nio .charset .StandardCharsets ;
6+ import java .util .Date ;
47import java .util .Iterator ;
58
9+ import org .bouncycastle .bcpg .AEADAlgorithmTags ;
610import org .bouncycastle .bcpg .ArmoredInputStream ;
711import org .bouncycastle .bcpg .BCPGInputStream ;
12+ import org .bouncycastle .bcpg .PublicKeyAlgorithmTags ;
13+ import org .bouncycastle .bcpg .PublicKeyPacket ;
14+ import org .bouncycastle .bcpg .SecretKeyPacket ;
15+ import org .bouncycastle .bcpg .SymmetricKeyAlgorithmTags ;
16+ import org .bouncycastle .jce .provider .BouncyCastleProvider ;
17+ import org .bouncycastle .openpgp .PGPException ;
818import org .bouncycastle .openpgp .PGPPublicKey ;
919import org .bouncycastle .openpgp .PGPPublicKeyRing ;
1020import org .bouncycastle .openpgp .PGPSecretKey ;
1121import org .bouncycastle .openpgp .PGPSecretKeyRing ;
1222import org .bouncycastle .openpgp .operator .KeyFingerPrintCalculator ;
1323import org .bouncycastle .openpgp .operator .bc .BcKeyFingerprintCalculator ;
14- import org .bouncycastle .util . Arrays ;
24+ import org .bouncycastle .openpgp . operator . jcajce . JcaKeyFingerprintCalculator ;
1525import org .bouncycastle .util .encoders .Hex ;
16- import org .bouncycastle .util .test .SimpleTest ;
1726
1827public class PGPv6KeyTest
19- extends SimpleTest
28+ extends AbstractPgpKeyPairTest
2029{
2130
2231 private static final String ARMORED_CERT = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n " +
@@ -45,9 +54,31 @@ public class PGPv6KeyTest
4554 "M0g12vYxoWM8Y81W+bHBw805I8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUr\n " +
4655 "k0mXubZvyl4GBg==\n " +
4756 "-----END PGP PRIVATE KEY BLOCK-----" ;
57+ // https://www.rfc-editor.org/rfc/rfc9580.html#name-sample-locked-version-6-sec
58+ private static final String ARMORED_PROTECTED_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n " +
59+ "\n " +
60+ "xYIGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laP9JgkC\n " +
61+ "FARdb9ccngltHraRe25uHuyuAQQVtKipJ0+r5jL4dacGWSAheCWPpITYiyfyIOPS\n " +
62+ "3gIDyg8f7strd1OB4+LZsUhcIjOMpVHgmiY/IutJkulneoBYwrEGHxsKAAAAQgWC\n " +
63+ "Y4d/4wMLCQcFFQoOCAwCFgACmwMCHgkiIQbLGGxPBgmml+TVLfpscisMHx4nwYpW\n " +
64+ "cI9lJewnutmsyQUnCQIHAgAAAACtKCAQPi19In7A5tfORHHbNr/JcIMlNpAnFJin\n " +
65+ "7wV2wH+q4UWFs7kDsBJ+xP2i8CMEWi7Ha8tPlXGpZR4UruETeh1mhELIj5UeM8T/\n " +
66+ "0z+5oX1RHu11j8bZzFDLX9eTsgOdWATHggZjh3/jGQAAACCGkySDZ/nlAV25Ivj0\n " +
67+ "gJXdp4SYfy1ZhbEvutFsr15ENf0mCQIUBA5hhGgp2oaavg6mFUXcFMwBBBUuE8qf\n " +
68+ "9Ock+xwusd+GAglBr5LVyr/lup3xxQvHXFSjjA2haXfoN6xUGRdDEHI6+uevKjVR\n " +
69+ "v5oAxgu7eJpaXNjCmwYYGwoAAAAsBYJjh3/jApsMIiEGyxhsTwYJppfk1S36bHIr\n " +
70+ "DB8eJ8GKVnCPZSXsJ7rZrMkAAAAABAEgpukYbZ1ZNfyP5WMUzbUnSGpaUSD5t2Ki\n " +
71+ "Nacp8DkBClZRa2c3AMQzSDXa9jGhYzxjzVb5scHDzTkjyRZWRdTq8U6L4da+/+Kt\n " +
72+ "ruh8m7Xo2ehSSFyWRSuTSZe5tm/KXgYG\n " +
73+ "-----END PGP PRIVATE KEY BLOCK-----" ;
74+ private static final Date CREATION_TIME = parseUTCTimestamp ("2022-11-30 16:08:03 UTC" );
75+
4876 private static final byte [] PRIMARY_FINGERPRINT = Hex .decode ("CB186C4F0609A697E4D52DFA6C722B0C1F1E27C18A56708F6525EC27BAD9ACC9" );
4977 private static final byte [] SUBKEY_FINGERPRINT = Hex .decode ("12C83F1E706F6308FE151A417743A1F033790E93E9978488D1DB378DA9930885" );
78+ private static final long PRIMARY_KEYID = -3812177997909612905L ;
79+ private static final long SUBKEY_KEYID = 1353401087992750856L ;
5080
81+ private static final KeyFingerPrintCalculator fingerPrintCalculator = new BcKeyFingerprintCalculator ();
5182
5283 @ Override
5384 public String getName ()
@@ -59,7 +90,15 @@ public String getName()
5990 public void performTest ()
6091 throws Exception
6192 {
62- KeyFingerPrintCalculator fingerPrintCalculator = new BcKeyFingerprintCalculator ();
93+ parseUnprotectedCertTest ();
94+ parseUnprotectedKeyTest ();
95+ testJcaFingerprintCalculation ();
96+ parseProtectedKeyTest ();
97+ }
98+
99+ private void parseUnprotectedCertTest ()
100+ throws IOException
101+ {
63102 ByteArrayInputStream bIn = new ByteArrayInputStream (ARMORED_CERT .getBytes ());
64103 ArmoredInputStream armorIn = new ArmoredInputStream (bIn );
65104 BCPGInputStream bcIn = new BCPGInputStream (armorIn );
@@ -68,22 +107,112 @@ public void performTest()
68107
69108 Iterator <PGPPublicKey > pIt = publicKeys .getPublicKeys ();
70109 PGPPublicKey key = (PGPPublicKey )pIt .next ();
71- isTrue (key .hasFingerprint (PRIMARY_FINGERPRINT ));
110+ isTrue ("Primary key fingerprint mismatch" , key .hasFingerprint (PRIMARY_FINGERPRINT ));
111+ isEquals ("Primary key-ID mismatch" , PRIMARY_KEYID , key .getKeyID ());
112+ isEquals ("Primary key version mismatch" , PublicKeyPacket .VERSION_6 , key .getVersion ());
113+ isEquals ("Primary key creation time mismatch" , CREATION_TIME , key .getCreationTime ());
114+ isEquals ("Primary key bit-strength mismatch" , 256 , key .getBitStrength ());
115+
72116 key = (PGPPublicKey )pIt .next ();
73- isTrue (key .hasFingerprint (SUBKEY_FINGERPRINT ));
117+ isTrue ("Subkey fingerprint mismatch" , key .hasFingerprint (SUBKEY_FINGERPRINT ));
118+ isEquals ("Subkey key-ID mismatch" , SUBKEY_KEYID , key .getKeyID ());
119+ isEquals ("Subkey version mismatch" , PublicKeyPacket .VERSION_6 , key .getVersion ());
120+ isEquals ("Subkey creation time mismatch" , CREATION_TIME , key .getCreationTime ());
121+ isEquals ("Subkey bit-strength mismatch" , 256 , key .getBitStrength ());
74122
75- bIn = new ByteArrayInputStream (ARMORED_KEY .getBytes ());
76- armorIn = new ArmoredInputStream (bIn );
77- bcIn = new BCPGInputStream (armorIn );
123+ isFalse ("Unexpected key object in key ring" , pIt .hasNext ());
124+ }
125+
126+ private void parseUnprotectedKeyTest ()
127+ throws IOException , PGPException
128+ {
129+ ByteArrayInputStream bIn = new ByteArrayInputStream (ARMORED_KEY .getBytes ());
130+ ArmoredInputStream armorIn = new ArmoredInputStream (bIn );
131+ BCPGInputStream bcIn = new BCPGInputStream (armorIn );
78132
79133 PGPSecretKeyRing secretKeys = new PGPSecretKeyRing (bcIn , fingerPrintCalculator );
80134
81135 Iterator <PGPSecretKey > sIt = secretKeys .getSecretKeys ();
82- PGPSecretKey sKey = (PGPSecretKey )sIt .next ();
83- isTrue (Arrays .areEqual (PRIMARY_FINGERPRINT , sKey .getFingerprint ()));
136+ PGPSecretKey key = (PGPSecretKey )sIt .next ();
137+ isEncodingEqual ("Primary key fingerprint mismatch" , PRIMARY_FINGERPRINT , key .getFingerprint ());
138+ isEquals ("Primary key-ID mismatch" , PRIMARY_KEYID , key .getKeyID ());
139+ isEquals ("Primary key version mismatch" , PublicKeyPacket .VERSION_6 , key .getPublicKey ().getVersion ());
140+ isEquals ("Primary key creation time mismatch" , CREATION_TIME , key .getPublicKey ().getCreationTime ());
141+ isEquals ("Primary key S2K-usage mismatch" , SecretKeyPacket .USAGE_NONE , key .getS2KUsage ());
142+ isNull ("Primary key S2K MUST be null" , key .getS2K ());
143+
144+ key = (PGPSecretKey )sIt .next ();
145+ isEncodingEqual ("Subkey fingerprint mismatch" , SUBKEY_FINGERPRINT , key .getFingerprint ());
146+ isEquals ("Subkey key-ID mismatch" , SUBKEY_KEYID , key .getKeyID ());
147+ isEquals ("Subkey version mismatch" , PublicKeyPacket .VERSION_6 , key .getPublicKey ().getVersion ());
148+ isEquals ("Subkey creation time mismatch" , CREATION_TIME , key .getPublicKey ().getCreationTime ());
149+ isEquals ("Subkey S2K-usage mismatch" , SecretKeyPacket .USAGE_NONE , key .getS2KUsage ());
150+ isNull ("Subkey S2K MUST be null" , key .getS2K ());
151+
152+ isFalse ("Unexpected key object in key ring" , sIt .hasNext ());
153+ }
154+
155+ private void testJcaFingerprintCalculation ()
156+ throws IOException
157+ {
158+ ByteArrayInputStream bIn = new ByteArrayInputStream (ARMORED_CERT .getBytes ());
159+ ArmoredInputStream armorIn = new ArmoredInputStream (bIn );
160+ BCPGInputStream bcIn = new BCPGInputStream (armorIn );
161+
162+ JcaKeyFingerprintCalculator fpCalc = new JcaKeyFingerprintCalculator ();
163+ fpCalc .setProvider (new BouncyCastleProvider ());
164+ PGPPublicKeyRing publicKeys = new PGPPublicKeyRing (bcIn , fpCalc );
165+
166+ Iterator <PGPPublicKey > pIt = publicKeys .getPublicKeys ();
167+ PGPPublicKey key = (PGPPublicKey )pIt .next ();
168+ isTrue ("Primary key fingerprint mismatch" , key .hasFingerprint (PRIMARY_FINGERPRINT ));
169+ isEquals ("Primary key-ID mismatch" , PRIMARY_KEYID , key .getKeyID ());
170+ key = (PGPPublicKey )pIt .next ();
171+ isTrue ("Subkey fingerprint mismatch" , key .hasFingerprint (SUBKEY_FINGERPRINT ));
172+ isEquals ("Subkey key-ID mismatch" , SUBKEY_KEYID , key .getKeyID ());
173+ }
174+
175+ private void parseProtectedKeyTest ()
176+ throws IOException , PGPException
177+ {
178+ ByteArrayInputStream bIn = new ByteArrayInputStream (ARMORED_PROTECTED_KEY .getBytes (StandardCharsets .UTF_8 ));
179+ ArmoredInputStream aIn = new ArmoredInputStream (bIn );
180+ BCPGInputStream pIn = new BCPGInputStream (aIn );
181+
182+ PGPSecretKeyRing secretKeys = new PGPSecretKeyRing (pIn , fingerPrintCalculator );
183+ Iterator <PGPSecretKey > sIt = secretKeys .getSecretKeys ();
184+
185+ PGPSecretKey key = sIt .next ();
186+ isEncodingEqual ("Primary key fingerprint mismatch" , PRIMARY_FINGERPRINT , key .getFingerprint ());
187+ isEquals ("Primary key ID mismatch" , PRIMARY_KEYID , key .getKeyID ());
188+ isEquals ("Primary key algorithm mismatch" ,
189+ PublicKeyAlgorithmTags .Ed25519 , key .getPublicKey ().getAlgorithm ());
190+ isEquals ("Primary key version mismatch" , PublicKeyPacket .VERSION_6 , key .getPublicKey ().getVersion ());
191+ isEquals ("Primary key creation time mismatch" , CREATION_TIME , key .getPublicKey ().getCreationTime ());
192+ isEquals ("Primary key S2K-Usage mismatch" , SecretKeyPacket .USAGE_AEAD , key .getS2KUsage ());
193+ isEquals ("Primary key AEAD algorithm mismatch" ,
194+ AEADAlgorithmTags .OCB , key .getAEADKeyEncryptionAlgorithm ());
195+ isEquals ("Primary key protection algorithm mismatch" ,
196+ SymmetricKeyAlgorithmTags .AES_256 , key .getKeyEncryptionAlgorithm ());
197+ isEncodingEqual ("Primary key S2K salt mismatch" ,
198+ Hex .decode ("5d6fd71c9e096d1eb6917b6e6e1eecae" ), key .getS2K ().getIV ());
199+
200+ key = sIt .next ();
201+ isEncodingEqual ("Subkey fingerprint mismatch" , SUBKEY_FINGERPRINT , key .getFingerprint ());
202+ isEquals ("Subkey ID mismatch" , SUBKEY_KEYID , key .getKeyID ());
203+ isEquals ("Subkey algorithm mismatch" ,
204+ PublicKeyAlgorithmTags .X25519 , key .getPublicKey ().getAlgorithm ());
205+ isEquals ("Subkey version mismatch" , PublicKeyPacket .VERSION_6 , key .getPublicKey ().getVersion ());
206+ isEquals ("Subkey creation time mismatch" , CREATION_TIME , key .getPublicKey ().getCreationTime ());
207+ isEquals ("Subkey S2K-Usage mismatch" , SecretKeyPacket .USAGE_AEAD , key .getS2KUsage ());
208+ isEquals ("Subkey AEAD algorithm mismatch" ,
209+ AEADAlgorithmTags .OCB , key .getAEADKeyEncryptionAlgorithm ());
210+ isEquals ("Subkey protection algorithm mismatch" ,
211+ SymmetricKeyAlgorithmTags .AES_256 , key .getKeyEncryptionAlgorithm ());
212+ isEncodingEqual ("Subkey S2K salt mismatch" ,
213+ Hex .decode ("0e61846829da869abe0ea61545dc14cc" ), key .getS2K ().getIV ());
84214
85- sKey = (PGPSecretKey )sIt .next ();
86- isTrue (Arrays .areEqual (SUBKEY_FINGERPRINT , sKey .getFingerprint ()));
215+ isFalse ("Unexpected key in key ring" , sIt .hasNext ());
87216 }
88217
89218 public static void main (String [] args )
0 commit comments