java - 使用 Bouncy Castle 的三重 DES Java 实现返回意外结果
问题描述
我正在尝试使用 Bouncy Castle 在我的 Java 应用程序中实现三重 DES 加密(DESede/ECB w/ ZeroPadding)。我遇到了一个问题,即从实现返回的加密值与预期的加密值不匹配。
如果 key = "987ff3cc1e3d58d4a698985201d02aed" 和 unencryptedString = "4548812028759309-0394-123",我希望得到的加密字符串等于 "6d2db19ab8ff3ae7c59ef7af0813c84eabe7c8e551fedfcffc94a607a06b293"。我的实现返回“b8b63dc7c1ec5330b4e19e1210180a1ffa66936298ed8032ea38b7febb9ece98”。
我在看什么?
使用 Bouncy Castle 实现三重 DES
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Security;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
public class TripleDESEncryptor {
private static final String UNICODE_FORMAT = "UTF8";
private static final String DESEDE_ECB_ENCRYPTION_SCHEME = "DESede/ECB/NoPadding";
private static final String DESEDE_ENCRYPTION_SCHEME = "DESede";
private static String BOUNCY_CASTLE_FIPS_PROVIDER = "BCFIPS";
private final Cipher cipher;
private final SecretKey key;
public TripleDESEncryptor(byte[] encryptionKey) {
try {
ensureBouncyCastleFIPSProviderIsAvailable();
cipher = Cipher.getInstance(DESEDE_ECB_ENCRYPTION_SCHEME, BOUNCY_CASTLE_FIPS_PROVIDER);
key = SecretKeyFactory
.getInstance(DESEDE_ENCRYPTION_SCHEME, BOUNCY_CASTLE_FIPS_PROVIDER)
.generateSecret(new DESedeKeySpec(encryptionKey));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String encrypt(String unencryptedString)
throws InvalidKeyException, InvalidAlgorithmParameterException,
UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] paddedPlainText = padWithZeroBytes(unencryptedString.getBytes(UNICODE_FORMAT));
return Hex.encodeHexString(cipher.doFinal(paddedPlainText));
}
private byte[] padWithZeroBytes(byte[] unencryptedString) {
return Arrays.copyOf(unencryptedString, roundUpToMultipleOf8(unencryptedString.length));
}
private int roundUpToMultipleOf8(int x) {
return ((x + 7) & (-8));
}
private void ensureBouncyCastleFIPSProviderIsAvailable() {
var bcfProvider = Arrays.stream(Security.getProviders())
.filter(provider -> BOUNCY_CASTLE_FIPS_PROVIDER.equals(provider.getName()))
.findAny().orElse(null);
if (bcfProvider == null)
Security.addProvider(new BouncyCastleFipsProvider());
}
}
单元测试
import static org.junit.Assert.assertEquals;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import org.junit.Test;
public class TripleDESEncryptorTest {
@Test
public void encrypt()
throws InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException,
BadPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException {
byte[] key = "987ff3cc1e3d58d4a698985201d02aed".getBytes("UTF8");
var encryptor = new TripleDESEncryptor(key);
String cleartext = "4548812028759309-0394-123";
String encrypted = encryptor.encrypt(cleartext);
assertEquals("6d2db19ab8ff3ae7c59ef7af0813c84eabe7c8e551fedfc94a607a06b239f4ef", encrypted);
}
}
解决方案
推荐阅读
- macos - 如何在带有 chrome 驱动程序的 macos 上使用 selenium 关闭选项卡?
- python - 如何使用数据框信息来分隔不同列表中不同类型的列?
- mysql - 使用 Docker-Compose 连接到 MariaDB 时出错,“连接丢失:服务器关闭了连接”
- c# - c#:如何创建解决方案范围的 ODBC 连接?
- css - Bootstrap 显示列并排
- web3 - javascript web3.js 库错误
- artifactory - jfrog artifactory 6.0.3 - 缺少管理模块 - 高级功能(检查系统信息等)
- html - 如何将两个元素并排放置
- python - 从 MultiIndex Dataffame 中删除单行
- apache-camel - Camel JdbcMessageIdRepository 键在从路由而不是 onCompletion 之后插入