我正在尝试实现一个接收字符串的函数,并返回CAST-256中String的编码值。以下代码是我在BoncyCastle官方网页(http://www.bouncycastle.org/specifications.html,第4.1点)上的示例后实现的。
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.engines.CAST6Engine;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
public class Test {
static{
Security.addProvider(new BouncyCastleProvider());
}
public static final String UTF8 = "utf-8";
public static final String KEY = "CLp4j13gADa9AmRsqsXGJ";
public static byte[] encrypt(String inputString) throws UnsupportedEncodingException {
final BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CAST6Engine());
byte[] key = KEY.getBytes(UTF8);
byte[] input = inputString.getBytes(UTF8);
cipher.init(true, new KeyParameter(key));
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int outputLen = cipher.processBytes(input, 0, input.length, cipherText, 0);
try {
cipher.doFinal(cipherText, outputLen);
} catch (CryptoException ce) {
System.err.println(ce);
System.exit(1);
}
return cipherText;
}
public static void main(String[] args) throws UnsupportedEncodingException {
final String toEncrypt = "hola";
final String encrypted = new String(Base64.encode(test(toEncrypt)),UTF8);
System.out.println(encrypted);
}
}
但是,当我运行我的代码时,我得到了
QUrYzMVlbx3OK6IKXWq1ng==
如果您使用相同的密钥在CAST-256中编码hola
(如果您需要http://www.tools4noobs.com/online_tools/encrypt/,请尝试此处)我应该
w5nZSYEyA8HuPL5V0J29Yg==
。
发生了什么事?为什么我得到一个wront加密字符串?
我厌倦了在互联网上找到并没有找到答案。
答案 0 :(得分:0)
Bouncy Castle默认使用PKCS#7填充,而PHP的mcrypt(以及您链接的网站)默认使用零填充。这会导致不同的密文。
请注意,此处使用的ECB模式几乎不能用于任何用途。另外,我希望你发布的密钥不是真正的密钥,因为现在它不再是秘密,所有这些加密都是无用的。
答案 1 :(得分:0)
这并没有真正回答你的问题,但确实提供了一些指示。
您需要进行一些挖掘,以确保您以与PHP mcrypt()
完全相同的方式进行解密。您需要确保密钥生成,编码/解码和密码算法完全匹配。
键
"CLp4j13gADa9AmRsqsXGJ".getBytes("UTF-8");
可能不是创建密钥源字节的正确方法。 docs似乎表示mcrypt()
填充了\0
的密钥和数据,如果它的大小不正确。请注意,您的方法生成一个168位密钥,这不是一个有效的密钥大小,我不确定java会对它做什么。
<强>算法强>
确保密码模式和填充是相同的。 mcrypt()
是否使用ECB,CBC,还有其他什么?
<强>编码
密码工作在字节上,而不是字符串。确保你在两者之间的转换在java和PHP中是相同的。
以下是使用来自http://tools.ietf.org/html/rfc2612#page-10的测试向量的CAST6的参考测试。注意密钥,密文和明文是十六进制编码的。
import java.security.Provider;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class Cast6 {
static final String KEY_ALGO = "CAST6";
static final String CIPHER_ALGO = "CAST6/ECB/NOPADDING";
static String keytext = "2342bb9efa38542c0af75647f29f615d";
static String plaintext = "00000000000000000000000000000000";
static String ciphertext = "c842a08972b43d20836c91d1b7530f6b";
static Provider bc = new BouncyCastleProvider();
public static void main(String[] args) throws Exception {
System.out.println("encrypting");
String actual = encrypt();
System.out.println("actual: " + actual);
System.out.println("expect: " + ciphertext);
System.out.println("decrypting");
actual = decrypt();
System.out.println("actual: " + actual);
System.out.println("expect: " + plaintext);
}
static String encrypt() throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGO, bc);
byte[] keyBytes = Hex.decodeHex(keytext.toCharArray());
SecretKeySpec key = new SecretKeySpec(keyBytes, KEY_ALGO);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] input = Hex.decodeHex(plaintext.toCharArray());
byte[] output = cipher.doFinal(input);
String actual = Hex.encodeHexString(output);
return actual;
}
static String decrypt() throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGO, bc);
byte[] keyBytes = Hex.decodeHex(keytext.toCharArray());
SecretKeySpec key = new SecretKeySpec(keyBytes, KEY_ALGO);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] output = cipher.doFinal(Hex.decodeHex(ciphertext.toCharArray()));
String actual = Hex.encodeHexString(output);
return actual;
}
}