Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions JenkinsfilePerformance
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ pipeline {
'ibm.jceplus.jmh.MessageDigestBenchmark', \
'ibm.jceplus.jmh.MessageDigestInstanceBenchmark', \
'ibm.jceplus.jmh.MLDSABenchmark', \
'ibm.jceplus.jmh.PBEBenchmark', \
'ibm.jceplus.jmh.PBKDF2Benchmark', \
'ibm.jceplus.jmh.RandomBenchmark', \
'ibm.jceplus.jmh.RSAKeyGeneratorBenchmark', \
Expand Down
331 changes: 194 additions & 137 deletions README.md

Large diffs are not rendered by default.

131 changes: 131 additions & 0 deletions src/main/java/com/ibm/crypto/plus/provider/OpenJCEPlus.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,14 @@ public final class OpenJCEPlus extends OpenJCEPlusProvider {

private static final String info = "OpenJCEPlus Provider implements the following:\n"
+ "Algorithm parameter : AES, ChaCha20, ChaCha20-Poly1305, DESede, DiffieHellman, DSA, EC, XEC, GCM, CCM, OAEP, RSAPSS\n"
+ " PBEWithHmacSHA1AndAES_128, PBEWithHmacSHA1AndAES_256, PBEWithHmacSHA224AndAES_128, PBEWithHmacSHA224AndAES_256\n"
+ " PBEWithHmacSHA256AndAES_128, PBEWithHmacSHA256AndAES_256, PBEWithHmacSHA384AndAES_128, PBEWithHmacSHA384AndAES_256\n"
+ " PBEWithHmacSHA512AndAES_128, PBEWithHmacSHA512AndAES_256\n"
+ "Algorithm parameter generator : DiffieHellman, DSA, EC, XEC, GCM, CCM\n"
+ "Cipher algorithms : AES, ChaCha20, ChaCha20-Poly1305, DESede, RSA\n"
+ " PBEWithHmacSHA1AndAES_128, PBEWithHmacSHA1AndAES_256, PBEWithHmacSHA224AndAES_128, PBEWithHmacSHA224AndAES_256\n"
+ " PBEWithHmacSHA256AndAES_128, PBEWithHmacSHA256AndAES_256, PBEWithHmacSHA384AndAES_128, PBEWithHmacSHA384AndAES_256\n"
+ " PBEWithHmacSHA512AndAES_128, PBEWithHmacSHA512AndAES_256\n"
+ "Key agreement algorithms : DiffieHellman, ECDH, XDH\n"
+ "Key factory : DiffieHellman, DSA, EC, XEC, RSA, RSAPSS\n"
+ "Key generator : AES, ChaCha20, DESede, HmacMD5, HmacSHA1, HmacSHA224,\n"
Expand All @@ -48,6 +54,9 @@ public final class OpenJCEPlus extends OpenJCEPlusProvider {
+ "Message digest : MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256, SHA3-224, SHA3-256, SHA3-384, SHA3-512\n"
+ "Secret key factory : AES, ChaCha20, DESede, PBKDF2WithHmacSHA1, PBKDF2WithHmacSHA224, PBKDF2WithHmacSHA256, PBKDF2WithHmacSHA384, PBKDF2WithHmacSHA512\n"
+ " PBKDF2WithHmacSHA512/224, PBKDF2WithHmacSHA512/256\n"
+ " PBEWithHmacSHA1AndAES_128, PBEWithHmacSHA1AndAES_256, PBEWithHmacSHA224AndAES_128, PBEWithHmacSHA224AndAES_256\n"
+ " PBEWithHmacSHA256AndAES_128, PBEWithHmacSHA256AndAES_256, PBEWithHmacSHA384AndAES_128, PBEWithHmacSHA384AndAES_256\n"
+ " PBEWithHmacSHA512AndAES_128, PBEWithHmacSHA512AndAES_256\n"
+ "Secure random : HASHDRBG, SHA256DRBG, SHA512DRBG\n"
+ "Signature algorithms : NONEwithDSA, SHA1withDSA, SHA224withDSA, SHA256withDSA,\n"
+ " SHA3-224withDSA, SHA3-256withDSA, SHA3-384withDSA, SHA3-512withDSA,\n"
Expand Down Expand Up @@ -150,7 +159,47 @@ private void registerAlgorithms(Provider jce) {
aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "OAEP",
"com.ibm.crypto.plus.provider.OAEPParameters", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithHmacSHA1AndAES_128",
"com.ibm.crypto.plus.provider.PBES2Parameters$HmacSHA1AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithHmacSHA1AndAES_256",
"com.ibm.crypto.plus.provider.PBES2Parameters$HmacSHA1AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithHmacSHA224AndAES_128",
"com.ibm.crypto.plus.provider.PBES2Parameters$HmacSHA224AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithHmacSHA224AndAES_256",
"com.ibm.crypto.plus.provider.PBES2Parameters$HmacSHA224AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithHmacSHA256AndAES_128",
"com.ibm.crypto.plus.provider.PBES2Parameters$HmacSHA256AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithHmacSHA256AndAES_256",
"com.ibm.crypto.plus.provider.PBES2Parameters$HmacSHA256AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithHmacSHA384AndAES_128",
"com.ibm.crypto.plus.provider.PBES2Parameters$HmacSHA384AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithHmacSHA384AndAES_256",
"com.ibm.crypto.plus.provider.PBES2Parameters$HmacSHA384AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithHmacSHA512AndAES_128",
"com.ibm.crypto.plus.provider.PBES2Parameters$HmacSHA512AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "AlgorithmParameters", "PBEWithHmacSHA512AndAES_256",
"com.ibm.crypto.plus.provider.PBES2Parameters$HmacSHA512AndAES_256", aliases));

/*aliases = null;
putService(new OpenJCEPlusService(jce,
"AlgorithmParameters",
Expand Down Expand Up @@ -265,6 +314,47 @@ private void registerAlgorithms(Provider jce) {
putService(new OpenJCEPlusService(jce, "Cipher", "ChaCha20-Poly1305",
"com.ibm.crypto.plus.provider.ChaCha20Poly1305Cipher", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA1AndAES_128",
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA1AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA1AndAES_256",
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA1AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA224AndAES_128",
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA224AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA224AndAES_256",
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA224AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA256AndAES_128",
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA256AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA256AndAES_256",
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA256AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA384AndAES_128",
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA384AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA384AndAES_256",
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA384AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA512AndAES_128",
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA512AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "Cipher", "PBEWithHmacSHA512AndAES_256",
"com.ibm.crypto.plus.provider.PBES2Core$HmacSHA512AndAES_256", aliases));


/* =======================================================================
* Key agreement
* =======================================================================
Expand Down Expand Up @@ -670,6 +760,47 @@ private void registerAlgorithms(Provider jce) {
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "ChaCha20",
"com.ibm.crypto.plus.provider.ChaCha20KeyFactory", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA1AndAES_128",
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA1AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA1AndAES_256",
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA1AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA224AndAES_128",
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA224AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA224AndAES_256",
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA224AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA256AndAES_128",
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA256AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA256AndAES_256",
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA256AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA384AndAES_128",
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA384AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA384AndAES_256",
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA384AndAES_256", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA512AndAES_128",
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA512AndAES_128", aliases));

aliases = null;
putService(new OpenJCEPlusService(jce, "SecretKeyFactory", "PBEWithHmacSHA512AndAES_256",
"com.ibm.crypto.plus.provider.PBEKeyFactory$PBEWithHmacSHA512AndAES_256", aliases));


/* =======================================================================
* SecureRandom
* =======================================================================
Expand Down
185 changes: 185 additions & 0 deletions src/main/java/com/ibm/crypto/plus/provider/PBEKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/*
* Copyright IBM Corp. 2025
*
* This code is free software; you can redistribute it and/or modify it
* under the terms provided by IBM in the LICENSE file that accompanied
* this code, including the "Classpath" Exception described therein.
*/

package com.ibm.crypto.plus.provider;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.lang.ref.Reference;
import java.security.MessageDigest;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Locale;
import javax.crypto.SecretKey;
import javax.crypto.spec.PBEKeySpec;

final class PBEKey implements SecretKey {

private static final long serialVersionUID = 9223372036854775807L;

private byte[] key;

private final String type;

private boolean destroyed = false;

private OpenJCEPlusProvider provider = null;

/**
* Creates a PBE key from a given PBE key specification.
*
* @param keytype the given PBE key specification
*/
PBEKey(OpenJCEPlusProvider provider, PBEKeySpec keySpec, String keytype) throws InvalidKeySpecException {
char[] passwd = keySpec.getPassword();

if (passwd == null || passwd.length == 0) {
// Should allow an empty password.
passwd = new char[0];
}

for (char c : passwd) {
if (Character.isISOControl(c))
throw new InvalidKeySpecException("Invalid Password.");
}

this.key = PBEUtil.encodePassword(passwd);
Arrays.fill(passwd, '\0');
type = keytype;
this.provider = provider;
}

public byte[] getEncoded() {
try {
return key.clone();
} finally {
// prevent this from being cleaned for the above block
Reference.reachabilityFence(this);
}
}

public String getAlgorithm() {
return type;
}

public String getFormat() {
return "RAW";
}

@Override
public int hashCode() {
try {
int retval = 0;
for (int i = 1; i < this.key.length; i++) {
retval += this.key[i] * i;
}
return(retval ^ getAlgorithm().toLowerCase(Locale.ENGLISH).hashCode());
} finally {
// prevent this from being cleaned for the above block
Reference.reachabilityFence(this);
}
}

@Override
public boolean equals(Object obj) {
try {
if (obj == this)
return true;

SecretKey that;
if (!(obj instanceof SecretKey))
return false;
that = (SecretKey) obj;

if (isDestroyed() || that.isDestroyed()) {
return false;
}

if (!(that.getAlgorithm().equalsIgnoreCase(type)))
return false;

byte[] thatEncoded = that.getEncoded();
boolean ret = MessageDigest.isEqual(this.key, thatEncoded);
Arrays.fill(thatEncoded, (byte) 0x00);
return ret;
} finally {
// prevent this from being cleaned for the above block
Reference.reachabilityFence(this);
}
}

@Override
public void destroy() {
if (this.key != null) {
Arrays.fill(this.key, (byte) 0x00);
destroyed = true;
}
}

@Override
public boolean isDestroyed() {
return destroyed;
}

/**
* Restores the state of this object from the stream.
*
* @param s the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
if (key == null) {
throw new InvalidObjectException(
"PBEKey couldn't be deserialized");
}
byte[] temp = key;
key = temp.clone();
Arrays.fill(temp, (byte) 0x00);

// Accept "\0" to signify "zero-length password with no terminator".
if (!(key.length == 1 && key[0] == 0)) {
for (int i = 0; i < key.length; i++) {
if ((key[i] < '\u0020') || (key[i] > '\u007E')) {
throw new InvalidObjectException(
"PBEKey had non-ASCII chars");
}
}
}
}


/**
* Replace the PBE key to be serialized.
*
* @return the standard KeyRep object to be serialized
*
* @throws java.io.ObjectStreamException if a new object representing
* this PBE key could not be created
*/
private Object writeReplace() throws java.io.ObjectStreamException {
try {
return new JCEPlusKeyRep(JCEPlusKeyRep.Type.SECRET,
getAlgorithm(), getFormat(), getEncoded(), provider.getName());
} finally {
// prevent this from being cleaned for the above block
Reference.reachabilityFence(this);
}
}

protected void finalize() throws Throwable {
try {
destroy();
} finally {
super.finalize();
}
}
}
Loading