88import org .bouncycastle .bcpg .PublicKeyEncSessionPacket ;
99import org .bouncycastle .bcpg .SymmetricEncIntegrityPacket ;
1010import org .bouncycastle .bcpg .SymmetricKeyAlgorithmTags ;
11+ import org .bouncycastle .jce .provider .BouncyCastleProvider ;
12+ import org .bouncycastle .openpgp .PGPEncryptedDataList ;
13+ import org .bouncycastle .openpgp .PGPException ;
14+ import org .bouncycastle .openpgp .PGPLiteralData ;
15+ import org .bouncycastle .openpgp .PGPObjectFactory ;
16+ import org .bouncycastle .openpgp .PGPPadding ;
17+ import org .bouncycastle .openpgp .PGPPrivateKey ;
18+ import org .bouncycastle .openpgp .PGPPublicKeyEncryptedData ;
19+ import org .bouncycastle .openpgp .PGPSecretKey ;
20+ import org .bouncycastle .openpgp .PGPSecretKeyRing ;
21+ import org .bouncycastle .openpgp .bc .BcPGPObjectFactory ;
22+ import org .bouncycastle .openpgp .jcajce .JcaPGPObjectFactory ;
23+ import org .bouncycastle .openpgp .operator .PublicKeyDataDecryptorFactory ;
24+ import org .bouncycastle .openpgp .operator .bc .BcPublicKeyDataDecryptorFactory ;
25+ import org .bouncycastle .openpgp .operator .jcajce .JcePublicKeyDataDecryptorFactoryBuilder ;
26+ import org .bouncycastle .util .Arrays ;
1127import org .bouncycastle .util .encoders .Hex ;
28+ import org .bouncycastle .util .io .Streams ;
1229
1330import java .io .ByteArrayInputStream ;
1431import java .io .IOException ;
32+ import java .io .InputStream ;
1533import java .nio .charset .StandardCharsets ;
1634
1735public class EncryptedMessagePacketTest
1836 extends AbstractPacketTest
1937{
38+ // https://www.rfc-editor.org/rfc/rfc9580.html#name-sample-version-6-secret-key
39+ final String V6_SECRET_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n " +
40+ "\n " +
41+ "xUsGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laMAGXKB\n " +
42+ "exK+cH6NX1hs5hNhIB00TrJmosgv3mg1ditlsLfCsQYfGwoAAABCBYJjh3/jAwsJ\n " +
43+ "BwUVCg4IDAIWAAKbAwIeCSIhBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce6\n " +
44+ "2azJBScJAgcCAAAAAK0oIBA+LX0ifsDm185Ecds2v8lwgyU2kCcUmKfvBXbAf6rh\n " +
45+ "RYWzuQOwEn7E/aLwIwRaLsdry0+VcallHhSu4RN6HWaEQsiPlR4zxP/TP7mhfVEe\n " +
46+ "7XWPxtnMUMtf15OyA51YBMdLBmOHf+MZAAAAIIaTJINn+eUBXbki+PSAld2nhJh/\n " +
47+ "LVmFsS+60WyvXkQ1AE1gCk95TUR3XFeibg/u/tVY6a//1q0NWC1X+yui3O24wpsG\n " +
48+ "GBsKAAAALAWCY4d/4wKbDCIhBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce6\n " +
49+ "2azJAAAAAAQBIKbpGG2dWTX8j+VjFM21J0hqWlEg+bdiojWnKfA5AQpWUWtnNwDE\n " +
50+ "M0g12vYxoWM8Y81W+bHBw805I8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUr\n " +
51+ "k0mXubZvyl4GBg==\n " +
52+ "-----END PGP PRIVATE KEY BLOCK-----\n " ;
53+
54+ // https://www.rfc-editor.org/rfc/rfc9580.html#name-complete-x25519-aead-ocb-en
55+ final String X25519_AEAD_OCB_MESSAGE = "-----BEGIN PGP MESSAGE-----\n " +
56+ "\n " +
57+ "wV0GIQYSyD8ecG9jCP4VGkF3Q6HwM3kOk+mXhIjR2zeNqZMIhRmHzxjV8bU/gXzO\n " +
58+ "WgBM85PMiVi93AZfJfhK9QmxfdNnZBjeo1VDeVZheQHgaVf7yopqR6W1FT6NOrfS\n " +
59+ "aQIHAgZhZBZTW+CwcW1g4FKlbExAf56zaw76/prQoN+bAzxpohup69LA7JW/Vp0l\n " +
60+ "yZnuSj3hcFj0DfqLTGgr4/u717J+sPWbtQBfgMfG9AOIwwrUBqsFE9zW+f1zdlYo\n " +
61+ "bhF30A+IitsxxA==\n " +
62+ "-----END PGP MESSAGE-----" ;
63+
2064 @ Override
2165 public String getName ()
2266 {
@@ -27,9 +71,125 @@ public String getName()
2771 public void performTest ()
2872 throws Exception
2973 {
74+ testX25519AEADOCBTestVector_bc ();
75+ testX25519AEADOCBTestVector_jce ();
76+ testPKESK6SEIPD2FromTestVector ();
3077 testPKESK6SEIPD2 ();
3178 }
3279
80+ private void testPKESK6SEIPD2FromTestVector ()
81+ throws IOException , PGPException
82+ {
83+ // https://www.rfc-editor.org/rfc/rfc9580.html#name-sample-version-6-public-key
84+ byte [] pkesk = Hex .decode ("c15d06210612c83f" +
85+ "1e706f6308fe151a" +
86+ "417743a1f033790e" +
87+ "93e9978488d1db37" +
88+ "8da99308851987cf" +
89+ "18d5f1b53f817cce" +
90+ "5a004cf393cc8958" +
91+ "bddc065f25f84af5" +
92+ "09b17dd3676418de" +
93+ "a355437956617901" +
94+ "e06957fbca8a6a47" +
95+ "a5b5153e8d3ab7" );
96+
97+ // https://www.rfc-editor.org/rfc/rfc9580.html#name-sample-v2-seipd-packet
98+ byte [] seipd = Hex .decode ("d269020702066164" +
99+ "16535be0b0716d60" +
100+ "e052a56c4c407f9e" +
101+ "b36b0efafe9ad0a0" +
102+ "df9b033c69a21ba9" +
103+ "ebd2c0ec95bf569d" +
104+ "25c999ee4a3de170" +
105+ "58f40dfa8b4c682b" +
106+ "e3fbbbd7b27eb0f5" +
107+ "9bb5005f80c7c6f4" +
108+ "0388c30ad406ab05" +
109+ "13dcd6f9fd737656" +
110+ "286e1177d00f888a" +
111+ "db31c4" );
112+
113+ ByteArrayInputStream bIn = new ByteArrayInputStream (V6_SECRET_KEY .getBytes (StandardCharsets .UTF_8 ));
114+ ArmoredInputStream aIn = new ArmoredInputStream (bIn );
115+ BCPGInputStream pIn = new BCPGInputStream (aIn );
116+ PGPObjectFactory objFac = new BcPGPObjectFactory (pIn );
117+ PGPSecretKeyRing secretKeys = (PGPSecretKeyRing ) objFac .nextObject ();
118+
119+ bIn = new ByteArrayInputStream (Arrays .concatenate (pkesk , seipd ));
120+ pIn = new BCPGInputStream (bIn );
121+ objFac = new BcPGPObjectFactory (pIn );
122+ PGPEncryptedDataList encList = (PGPEncryptedDataList ) objFac .nextObject ();
123+ PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData ) encList .get (0 );
124+ PGPSecretKey decKey = secretKeys .getSecretKey (encData .getKeyIdentifier ());
125+ PGPPrivateKey privKey = decKey .extractPrivateKey (null );
126+ PublicKeyDataDecryptorFactory decryptor = new BcPublicKeyDataDecryptorFactory (privKey );
127+ InputStream in = encData .getDataStream (decryptor );
128+ objFac = new BcPGPObjectFactory (in );
129+ PGPLiteralData literalData = (PGPLiteralData ) objFac .nextObject ();
130+ byte [] msg = Streams .readAll (literalData .getDataStream ());
131+ isEncodingEqual ("Hello, world!" .getBytes (StandardCharsets .UTF_8 ), msg );
132+ PGPPadding padding = (PGPPadding ) objFac .nextObject ();
133+ isEncodingEqual (Hex .decode ("c5a293072991628147d72c8f86b7" ), padding .getPadding ());
134+ }
135+
136+ private void testX25519AEADOCBTestVector_bc ()
137+ throws IOException , PGPException
138+ {
139+ ByteArrayInputStream bIn = new ByteArrayInputStream (V6_SECRET_KEY .getBytes (StandardCharsets .UTF_8 ));
140+ ArmoredInputStream aIn = new ArmoredInputStream (bIn );
141+ BCPGInputStream pIn = new BCPGInputStream (aIn );
142+ PGPObjectFactory objFac = new BcPGPObjectFactory (pIn );
143+ PGPSecretKeyRing secretKeys = (PGPSecretKeyRing ) objFac .nextObject ();
144+
145+ bIn = new ByteArrayInputStream (X25519_AEAD_OCB_MESSAGE .getBytes ());
146+ aIn = new ArmoredInputStream (bIn );
147+ pIn = new BCPGInputStream (aIn );
148+ objFac = new BcPGPObjectFactory (pIn );
149+ PGPEncryptedDataList encList = (PGPEncryptedDataList ) objFac .nextObject ();
150+ PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData ) encList .get (0 );
151+ PGPSecretKey decKey = secretKeys .getSecretKey (encData .getKeyIdentifier ());
152+ PGPPrivateKey privKey = decKey .extractPrivateKey (null );
153+ PublicKeyDataDecryptorFactory decryptor = new BcPublicKeyDataDecryptorFactory (privKey );
154+ InputStream in = encData .getDataStream (decryptor );
155+ objFac = new BcPGPObjectFactory (in );
156+ PGPLiteralData literalData = (PGPLiteralData ) objFac .nextObject ();
157+ byte [] plaintext = Streams .readAll (literalData .getDataStream ());
158+ isEncodingEqual ("Hello, world!" .getBytes (StandardCharsets .UTF_8 ), plaintext );
159+ PGPPadding padding = (PGPPadding ) objFac .nextObject ();
160+ isEncodingEqual (Hex .decode ("c5a293072991628147d72c8f86b7" ), padding .getPadding ());
161+ }
162+
163+ private void testX25519AEADOCBTestVector_jce ()
164+ throws IOException , PGPException
165+ {
166+ ByteArrayInputStream bIn = new ByteArrayInputStream (V6_SECRET_KEY .getBytes (StandardCharsets .UTF_8 ));
167+ ArmoredInputStream aIn = new ArmoredInputStream (bIn );
168+ BCPGInputStream pIn = new BCPGInputStream (aIn );
169+ PGPObjectFactory objFac = new JcaPGPObjectFactory (pIn );
170+ PGPSecretKeyRing secretKeys = (PGPSecretKeyRing ) objFac .nextObject ();
171+
172+ bIn = new ByteArrayInputStream (X25519_AEAD_OCB_MESSAGE .getBytes ());
173+ aIn = new ArmoredInputStream (bIn );
174+ pIn = new BCPGInputStream (aIn );
175+ objFac = new JcaPGPObjectFactory (pIn );
176+ PGPEncryptedDataList encList = (PGPEncryptedDataList ) objFac .nextObject ();
177+ PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData ) encList .get (0 );
178+ PGPSecretKey decKey = secretKeys .getSecretKey (encData .getKeyIdentifier ());
179+ PGPPrivateKey privKey = decKey .extractPrivateKey (null );
180+ PublicKeyDataDecryptorFactory decryptor = new JcePublicKeyDataDecryptorFactoryBuilder ()
181+ .setProvider (new BouncyCastleProvider ())
182+ .setContentProvider (new BouncyCastleProvider ())
183+ .build (privKey );
184+ InputStream in = encData .getDataStream (decryptor );
185+ objFac = new JcaPGPObjectFactory (in );
186+ PGPLiteralData literalData = (PGPLiteralData ) objFac .nextObject ();
187+ byte [] plaintext = Streams .readAll (literalData .getDataStream ());
188+ isEncodingEqual ("Hello, world!" .getBytes (StandardCharsets .UTF_8 ), plaintext );
189+ PGPPadding padding = (PGPPadding ) objFac .nextObject ();
190+ isEncodingEqual (Hex .decode ("c5a293072991628147d72c8f86b7" ), padding .getPadding ());
191+ }
192+
33193 private void testPKESK6SEIPD2 ()
34194 throws IOException
35195 {
0 commit comments