我需要使用密码生成的自定义密钥加密一些数据。
必须是: 3DES 密码模式:ECB 填充模式:零
我找不到任何代码来执行此操作。有人能告诉我一个例子吗?
我试过这个,它显示了以下错误
ERROR: java.security.InvalidAlgorithmParameterException: expected IV length of 0
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import javax.crypto.Cipher;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Encryption {
public static int MAX_KEY_LENGTH = DESedeKeySpec.DES_EDE_KEY_LEN;
private static String ENCRYPTION_KEY_TYPE = "DESede";
private static String ENCRYPTION_ALGORITHM = "DESede/ECB/PKCS5Padding";
private final SecretKeySpec keySpec;
public Encryption(String passphrase) {
byte[] key;
try {
// get bytes representation of the password
key = passphrase.getBytes("UTF8");
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException(e);
}
key = padKeyToLength(key, MAX_KEY_LENGTH);
keySpec = new SecretKeySpec(key, ENCRYPTION_KEY_TYPE);
}
// !!! - see post below
private byte[] padKeyToLength(byte[] key, int len) {
byte[] newKey = new byte[len];
System.arraycopy(key, 0, newKey, 0, Math.min(key.length, len));
return newKey;
}
// standard stuff
public byte[] encrypt(byte[] unencrypted) throws GeneralSecurityException {
return doCipher(unencrypted, Cipher.ENCRYPT_MODE);
}
public byte[] decrypt(byte[] encrypted) throws GeneralSecurityException {
return doCipher(encrypted, Cipher.DECRYPT_MODE);
}
private byte[] doCipher(byte[] original, int mode) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
// IV = 0 is yet another issue, we'll ignore it here
IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
cipher.init(mode, keySpec, iv);
return cipher.doFinal(original);
}
}
EDITED: 现在我有了这个,我传递了“passphrase”参数我的自定义键(键大小= 8) 我调用的php不接受加密结果(这不正确)。
正确的加密是这个网络确实把算法“三元组”和模式:ECB https://www.tools4noobs.com/online_tools/encrypt/
我还不知道我做错了什么......
public class Encryption {
public static int MAX_KEY_LENGTH = DESedeKeySpec.DES_EDE_KEY_LEN;
private static String ENCRYPTION_KEY_TYPE = "DESede";
private static String ENCRYPTION_ALGORITHM = "DESede/ECB/NoPadding";
private final SecretKeySpec keySpec;
public Encryption(String passphrase) {
byte[] key;
try {
// get bytes representation of the password
key = passphrase.getBytes("UTF8");
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException(e);
}
key = padKeyToLength(key, MAX_KEY_LENGTH);
keySpec = new SecretKeySpec(key, ENCRYPTION_KEY_TYPE);
}
private byte[] padKeyToLength(byte[] key, int len) {
byte[] newKey = new byte[len];
System.arraycopy(key, 0, newKey, 0, Math.min(key.length, len));
return newKey;
}
// standard stuff
public byte[] encrypt(byte[] unencrypted) throws GeneralSecurityException {
return doCipher(unencrypted, Cipher.ENCRYPT_MODE);
}
public byte[] decrypt(byte[] encrypted) throws GeneralSecurityException {
return doCipher(encrypted, Cipher.DECRYPT_MODE);
}
private byte[] doCipher(byte[] original, int mode) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
int bs = cipher.getBlockSize();
byte[] padded = new byte[original.length + bs - original.length % bs];
System.arraycopy(original, 0, padded, 0, original.length);
cipher.init(mode, keySpec);
return cipher.doFinal(padded);
}
答案 0 :(得分:0)
ECB模式不使用IV,这使得它成为确定性密码模式,这意味着它在语义上不安全。如果您仍然需要使用它,请删除IV作为参数:
int bs = cipher.getBlockSize();
byte[] padded = new byte[original.length + bs - original.length % bs];
System.arraycopy(original, 0, padded, 0, original.length);
cipher.init(mode, keySpec);
return cipher.doFinal(padded);
这将为您提供零填充消息,然后可以对其进行加密。这是有效的,因为字节数组总是初始化为零。填充与BouncyCastle的ZeroPadding相同。如果你想在PHP的mcrypt中做零填充,那么使用
byte[] padded = new byte[original.length + (bs - original.length % bs) % bs];
答案 1 :(得分:0)
以下是我用3DES加密内容的代码示例。我也使用Base64作为我的secretKey,但我想你会想到这一点。
public class KeywordsCipher {
private static final String PADDING = "DESede/ECB/NoPadding";
private static final String UTF_F8 = "UTF-8";
private static final String DE_SEDE = "DESede";
private String secretKey;
{...}
public String encrypt(String message, String secretKey) {
byte[] cipherText = null;
try {
final byte[] secretBase64Key = Base64.decodeBase64(secretKey);
final SecretKey key = new SecretKeySpec(secretBase64Key, DE_SEDE);
final Cipher cipher = Cipher.getInstance(PADDING);
cipher.init(Cipher.ENCRYPT_MODE, key);
final byte[] plainTextBytes = message.getBytes();
cipherText = cipher.doFinal(plainTextBytes);
} catch (NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException e) {
throw new CipherException("Problem with encryption occured");
}
return Hex.encodeHexString(cipherText);
}
public CipherKeywordModel decrypt(String keyToDecrypt, String secretKey) {
try {
byte[] message = DatatypeConverter.parseHexBinary(keyToDecrypt);
final byte[] secretBase64Key = Base64.decodeBase64(secretKey);
final SecretKey key = new SecretKeySpec(secretBase64Key, DE_SEDE);
final Cipher decipher = Cipher.getInstance(PADDING);
decipher.init(Cipher.DECRYPT_MODE, key);
final byte[] plainText = decipher.doFinal(message);
String decryptedText = new String(plainText, UTF_F8);
} catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException e) {
throw new CipherException("Problem with encryption occured");
}
return decryptedText;
}