Skip to content

Commit a6af2e3

Browse files
authored
Support for PBES1 algorithms (#1193)
This update adds support for PBES1, PBEKeyFactory, and PBEParameters for PBES1 algorithms with manual key derivation using MessageDigest with the hash iteration count loop implemented in C to avoid excess JNI calls. RC2 and RC4 Cipher classes have been added for PBE purpose only and these Ciphers are not supported by OpenJCEPlus Provider. PBE cipher tests have also been updated for better test coverage. Signed-off-by: Dev Agarwal <dev.agarwal@ibm.com>
1 parent 12a8336 commit a6af2e3

22 files changed

+2416
-178
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,11 @@ AlgorithmParameters | EC |X
301301
AlgorithmParameters | GCM |X |X | |
302302
AlgorithmParameters | OAEP |X |X | |
303303
AlgorithmParameters | RSAPSS |X |X | |
304+
AlgorithmParameters | PBEWithSHA1AndDESede | |X | |
305+
AlgorithmParameters | PBEWithSHA1AndRC2_40 | |X | |
306+
AlgorithmParameters | PBEWithSHA1AndRC2_128 | |X | |
307+
AlgorithmParameters | PBEWithSHA1AndRC4_40 | |X | |
308+
AlgorithmParameters | PBEWithSHA1AndRC4_128 | |X | |
304309
AlgorithmParameters | PBEWithHmacSHA1AndAES_128 | |X | |
305310
AlgorithmParameters | PBEWithHmacSHA1AndAES_256 | |X | |
306311
AlgorithmParameters | PBEWithHmacSHA224AndAES_128 | |X | |
@@ -318,6 +323,11 @@ Cipher | ChaCha20 |
318323
Cipher | ChaCha20-Poly1305 | |X | |
319324
Cipher | DESede | |X | |
320325
Cipher | RSA |X |X | |
326+
Cipher | PBEWithSHA1AndDESede | |X | |
327+
Cipher | PBEWithSHA1AndRC2_40 | |X | |
328+
Cipher | PBEWithSHA1AndRC2_128 | |X | |
329+
Cipher | PBEWithSHA1AndRC4_40 | |X | |
330+
Cipher | PBEWithSHA1AndRC4_128 | |X | |
321331
Cipher | PBEWithHmacSHA1AndAES_128 | |X | |
322332
Cipher | PBEWithHmacSHA1AndAES_256 | |X | |
323333
Cipher | PBEWithHmacSHA224AndAES_128 | |X | |
@@ -430,6 +440,11 @@ SecretKeyFactory | PBKDF2WithHmacSHA384 |X
430440
SecretKeyFactory | PBKDF2WithHmacSHA512 |X |X | |
431441
SecretKeyFactory | PBKDF2WithHmacSHA512/224 | |X | |
432442
SecretKeyFactory | PBKDF2WithHmacSHA512/256 | |X | |
443+
SecretKeyFactory | PBEWithSHA1AndDESede | |X | |
444+
SecretKeyFactory | PBEWithSHA1AndRC2_40 | |X | |
445+
SecretKeyFactory | PBEWithSHA1AndRC2_128 | |X | |
446+
SecretKeyFactory | PBEWithSHA1AndRC4_40 | |X | |
447+
SecretKeyFactory | PBEWithSHA1AndRC4_128 | |X | |
433448
SecretKeyFactory | PBEWithHmacSHA1AndAES_128 | |X | |
434449
SecretKeyFactory | PBEWithHmacSHA1AndAES_256 | |X | |
435450
SecretKeyFactory | PBEWithHmacSHA224AndAES_128 | |X | |

src/main/java/com/ibm/crypto/plus/provider/DESedeCipher.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,12 @@
2222
import java.util.Arrays;
2323
import javax.crypto.BadPaddingException;
2424
import javax.crypto.Cipher;
25-
import javax.crypto.CipherSpi;
2625
import javax.crypto.IllegalBlockSizeException;
2726
import javax.crypto.NoSuchPaddingException;
2827
import javax.crypto.ShortBufferException;
2928
import javax.crypto.spec.IvParameterSpec;
3029

31-
public final class DESedeCipher extends CipherSpi implements DESConstants {
30+
public final class DESedeCipher extends LegacyCipher implements DESConstants {
3231

3332
private OpenJCEPlusProvider provider = null;
3433
private SymmetricCipher symmetricCipher = null;
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright IBM Corp. 2026
3+
*
4+
* This code is free software; you can redistribute it and/or modify it
5+
* under the terms provided by IBM in the LICENSE file that accompanied
6+
* this code, including the "Classpath" Exception described therein.
7+
*/
8+
9+
package com.ibm.crypto.plus.provider;
10+
11+
import java.security.AlgorithmParameters;
12+
import java.security.InvalidAlgorithmParameterException;
13+
import java.security.InvalidKeyException;
14+
import java.security.Key;
15+
import java.security.NoSuchAlgorithmException;
16+
import java.security.SecureRandom;
17+
import java.security.spec.AlgorithmParameterSpec;
18+
import javax.crypto.BadPaddingException;
19+
import javax.crypto.CipherSpi;
20+
import javax.crypto.IllegalBlockSizeException;
21+
import javax.crypto.NoSuchPaddingException;
22+
import javax.crypto.ShortBufferException;
23+
24+
abstract class LegacyCipher extends CipherSpi {
25+
26+
@Override
27+
protected abstract byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
28+
throws IllegalBlockSizeException, BadPaddingException;
29+
30+
@Override
31+
protected abstract int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
32+
int outputOffset) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException;
33+
34+
@Override
35+
protected abstract int engineGetBlockSize();
36+
37+
@Override
38+
protected abstract int engineGetKeySize(Key key) throws InvalidKeyException;
39+
40+
@Override
41+
protected abstract byte[] engineGetIV();
42+
43+
@Override
44+
protected abstract int engineGetOutputSize(int inputLen);
45+
46+
@Override
47+
protected abstract AlgorithmParameters engineGetParameters();
48+
49+
@Override
50+
protected abstract void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException;
51+
52+
@Override
53+
protected abstract void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
54+
SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException;
55+
56+
@Override
57+
protected abstract void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random)
58+
throws InvalidKeyException, InvalidAlgorithmParameterException;
59+
60+
@Override
61+
protected abstract void engineSetMode(String mode) throws NoSuchAlgorithmException;
62+
63+
@Override
64+
protected abstract void engineSetPadding(String padding) throws NoSuchPaddingException;
65+
66+
@Override
67+
protected abstract byte[] engineUpdate(byte[] input, int inputOffset, int inputLen);
68+
69+
@Override
70+
protected abstract int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
71+
int outputOffset) throws ShortBufferException;
72+
73+
@Override
74+
protected abstract byte[] engineWrap(Key key) throws InvalidKeyException, IllegalBlockSizeException;
75+
76+
@Override
77+
protected abstract Key engineUnwrap(byte[] wrappedKey, String algorithm, int type)
78+
throws InvalidKeyException, NoSuchAlgorithmException;
79+
80+
}

src/main/java/com/ibm/crypto/plus/provider/MessageDigest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ protected int engineGetDigestLength() {
6565
}
6666
}
6767

68+
/*
69+
* This method helps in deriving PKCS12 key by performing update and digest in C
70+
* in an iteration count loop avoiding excess JNI calls.
71+
*/
72+
protected byte[] PKCS12KeyDeriveHelp(byte[] input, int offset, int length, int iterationCount) {
73+
try {
74+
return this.digest.PKCS12KeyDeriveHelp(input, offset, length, iterationCount);
75+
} catch (Exception e) {
76+
throw provider.providerException("Failure in PKCS12 key derivation native helper method", e);
77+
}
78+
}
79+
6880
/**
6981
* Compares two digests for equality. Two digests are equal if they have
7082
* the same length and all bytes at corresponding positions are equal.

src/main/java/com/ibm/crypto/plus/provider/OpenJCEPlus.java

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@ public final class OpenJCEPlus extends OpenJCEPlusProvider {
2626
+ "Algorithm parameter : AES, ChaCha20, ChaCha20-Poly1305, DESede, DiffieHellman, DSA, EC, XEC, GCM, CCM, OAEP, RSAPSS\n"
2727
+ " PBEWithHmacSHA1AndAES_128, PBEWithHmacSHA1AndAES_256, PBEWithHmacSHA224AndAES_128, PBEWithHmacSHA224AndAES_256\n"
2828
+ " PBEWithHmacSHA256AndAES_128, PBEWithHmacSHA256AndAES_256, PBEWithHmacSHA384AndAES_128, PBEWithHmacSHA384AndAES_256\n"
29-
+ " PBEWithHmacSHA512AndAES_128, PBEWithHmacSHA512AndAES_256\n"
29+
+ " PBEWithHmacSHA512AndAES_128, PBEWithHmacSHA512AndAES_256\n"
30+
+ " PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40, PBEWithSHA1AndRC2_128, PBEWithSHA1AndRC4_40, PBEWithSHA1AndRC4_128\n"
3031
+ "Algorithm parameter generator : DiffieHellman, DSA, EC, XEC, GCM, CCM\n"
3132
+ "Cipher algorithms : AES, ChaCha20, ChaCha20-Poly1305, DESede, RSA\n"
3233
+ " PBEWithHmacSHA1AndAES_128, PBEWithHmacSHA1AndAES_256, PBEWithHmacSHA224AndAES_128, PBEWithHmacSHA224AndAES_256\n"
3334
+ " PBEWithHmacSHA256AndAES_128, PBEWithHmacSHA256AndAES_256, PBEWithHmacSHA384AndAES_128, PBEWithHmacSHA384AndAES_256\n"
34-
+ " PBEWithHmacSHA512AndAES_128, PBEWithHmacSHA512AndAES_256\n"
35+
+ " PBEWithHmacSHA512AndAES_128, PBEWithHmacSHA512AndAES_256\n"
36+
+ " PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40, PBEWithSHA1AndRC2_128, PBEWithSHA1AndRC4_40, PBEWithSHA1AndRC4_128\n"
3537
+ "Key agreement algorithms : DiffieHellman, ECDH, XDH\n"
3638
+ "Key factory : DiffieHellman, DSA, EC, XEC, RSA, RSAPSS\n"
3739
+ "Key generator : AES, ChaCha20, DESede, HmacMD5, HmacSHA1, HmacSHA224,\n"
@@ -48,7 +50,8 @@ public final class OpenJCEPlus extends OpenJCEPlusProvider {
4850
+ " PBKDF2WithHmacSHA512/224, PBKDF2WithHmacSHA512/256\n"
4951
+ " PBEWithHmacSHA1AndAES_128, PBEWithHmacSHA1AndAES_256, PBEWithHmacSHA224AndAES_128, PBEWithHmacSHA224AndAES_256\n"
5052
+ " PBEWithHmacSHA256AndAES_128, PBEWithHmacSHA256AndAES_256, PBEWithHmacSHA384AndAES_128, PBEWithHmacSHA384AndAES_256\n"
51-
+ " PBEWithHmacSHA512AndAES_128, PBEWithHmacSHA512AndAES_256\n"
53+
+ " PBEWithHmacSHA512AndAES_128, PBEWithHmacSHA512AndAES_256\n"
54+
+ " PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40, PBEWithSHA1AndRC2_128, PBEWithSHA1AndRC4_40, PBEWithSHA1AndRC4_128\n"
5255
+ "Secure random : HASHDRBG, SHA256DRBG, SHA512DRBG\n"
5356
+ "Signature algorithms : NONEwithDSA, SHA1withDSA, SHA224withDSA, SHA256withDSA,\n"
5457
+ " SHA3-224withDSA, SHA3-256withDSA, SHA3-384withDSA, SHA3-512withDSA,\n"
@@ -203,6 +206,26 @@ private void registerAlgorithms(Provider jce) {
203206
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "ChaCha20-Poly1305",
204207
"com.ibm.crypto.plus.provider.ChaCha20Poly1305Parameters", aliases));
205208

209+
aliases = null;
210+
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithSHA1AndDESede",
211+
"com.ibm.crypto.plus.provider.PBEParameters", aliases));
212+
213+
aliases = null;
214+
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithSHA1AndRC2_40",
215+
"com.ibm.crypto.plus.provider.PBEParameters", aliases));
216+
217+
aliases = null;
218+
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithSHA1AndRC2_128",
219+
"com.ibm.crypto.plus.provider.PBEParameters", aliases));
220+
221+
aliases = null;
222+
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithSHA1AndRC4_40",
223+
"com.ibm.crypto.plus.provider.PBEParameters", aliases));
224+
225+
aliases = null;
226+
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithSHA1AndRC4_128",
227+
"com.ibm.crypto.plus.provider.PBEParameters", aliases));
228+
206229
/* =======================================================================
207230
* Algorithm parameter generation engines
208231
* =======================================================================
@@ -345,6 +368,26 @@ private void registerAlgorithms(Provider jce) {
345368
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA512AndAES_256",
346369
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA512AndAES_256", aliases));
347370

371+
aliases = null;
372+
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithSHA1AndDESede",
373+
"com.ibm.crypto.plus.provider.PBES1Core$PBEWithSHA1AndDESede", aliases));
374+
375+
aliases = null;
376+
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithSHA1AndRC2_40",
377+
"com.ibm.crypto.plus.provider.PBES1Core$PBEWithSHA1AndRC2_40", aliases));
378+
379+
aliases = null;
380+
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithSHA1AndRC2_128",
381+
"com.ibm.crypto.plus.provider.PBES1Core$PBEWithSHA1AndRC2_128", aliases));
382+
383+
aliases = null;
384+
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithSHA1AndRC4_40",
385+
"com.ibm.crypto.plus.provider.PBES1Core$PBEWithSHA1AndRC4_40", aliases));
386+
387+
aliases = null;
388+
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithSHA1AndRC4_128",
389+
"com.ibm.crypto.plus.provider.PBES1Core$PBEWithSHA1AndRC4_128", aliases));
390+
348391
/* =======================================================================
349392
* Key agreement
350393
* =======================================================================
@@ -787,6 +830,26 @@ private void registerAlgorithms(Provider jce) {
787830
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA512AndAES_256",
788831
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA512AndAES_256", aliases));
789832

833+
aliases = null;
834+
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithSHA1AndDESede",
835+
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithSHA1AndDESede", aliases));
836+
837+
aliases = null;
838+
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithSHA1AndRC2_40",
839+
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithSHA1AndRC2_40", aliases));
840+
841+
aliases = null;
842+
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithSHA1AndRC2_128",
843+
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithSHA1AndRC2_128", aliases));
844+
845+
aliases = null;
846+
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithSHA1AndRC4_40",
847+
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithSHA1AndRC4_40", aliases));
848+
849+
aliases = null;
850+
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithSHA1AndRC4_128",
851+
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithSHA1AndRC4_128", aliases));
852+
790853
/* =======================================================================
791854
* SecureRandom
792855
* =======================================================================

src/main/java/com/ibm/crypto/plus/provider/PBEKeyFactory.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright IBM Corp. 2025
2+
* Copyright IBM Corp. 2025, 2026
33
*
44
* This code is free software; you can redistribute it and/or modify it
55
* under the terms provided by IBM in the LICENSE file that accompanied
@@ -93,6 +93,36 @@ public PBEWithHmacSHA512AndAES_256(OpenJCEPlusProvider provider) {
9393
}
9494
}
9595

96+
public static final class PBEWithSHA1AndDESede extends PBEKeyFactory {
97+
public PBEWithSHA1AndDESede(OpenJCEPlusProvider provider) {
98+
super("PBEWithSHA1AndDESede", provider);
99+
}
100+
}
101+
102+
public static final class PBEWithSHA1AndRC2_40 extends PBEKeyFactory {
103+
public PBEWithSHA1AndRC2_40(OpenJCEPlusProvider provider) {
104+
super("PBEWithSHA1AndRC2_40", provider);
105+
}
106+
}
107+
108+
public static final class PBEWithSHA1AndRC2_128 extends PBEKeyFactory {
109+
public PBEWithSHA1AndRC2_128(OpenJCEPlusProvider provider) {
110+
super("PBEWithSHA1AndRC2_128", provider);
111+
}
112+
}
113+
114+
public static final class PBEWithSHA1AndRC4_40 extends PBEKeyFactory {
115+
public PBEWithSHA1AndRC4_40(OpenJCEPlusProvider provider) {
116+
super("PBEWithSHA1AndRC4_40", provider);
117+
}
118+
}
119+
120+
public static final class PBEWithSHA1AndRC4_128 extends PBEKeyFactory {
121+
public PBEWithSHA1AndRC4_128(OpenJCEPlusProvider provider) {
122+
super("PBEWithSHA1AndRC4_128", provider);
123+
}
124+
}
125+
96126
/**
97127
* Generates a <code>SecretKey</code> object from the provided key
98128
* specification (key material).

0 commit comments

Comments
 (0)