Java 使用BouncyCastle';加密/解密字节数组的最简单方法是什么;什么是分组密码?
如果我有一个Java 使用BouncyCastle';加密/解密字节数组的最简单方法是什么;什么是分组密码?,java,encryption,bouncycastle,Java,Encryption,Bouncycastle,如果我有一个BlockCipher和一个byte[]是从包含秘密消息的String中获得的,那么获得加密消息的byte[]最简单的方法是什么 在普通的JavaAPI中,我可以只执行cipher.doFinal(secretMessage),但这里似乎没有类似的操作,它只处理块 我知道我可以使用BufferedBlockCipher,但这仍然不能显著简化事情。使用此密码最简单的高级方法是什么?BouncyCastle实现了“普通Java API”,因此您可以使用cipher.doFinal(Str
BlockCipher
和一个byte[]
是从包含秘密消息的String
中获得的,那么获得加密消息的byte[]
最简单的方法是什么
在普通的JavaAPI中,我可以只执行cipher.doFinal(secretMessage)
,但这里似乎没有类似的操作,它只处理块
我知道我可以使用
BufferedBlockCipher
,但这仍然不能显著简化事情。使用此密码最简单的高级方法是什么?BouncyCastle实现了“普通Java API”,因此您可以使用cipher.doFinal(String.getBytes())
获取密码时只需指定提供程序“BC”:cipher.getInstance(“YourTransformation”,“BC”)
使用BouncyCastle的。它是最接近JavaAPI的东西
static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider();
public static void main(String[] args) throws Exception {
KeyGenerator kg = KeyGenerator.getInstance("Threefish-1024", PROVIDER);
kg.init(1024);
KeyParameter key = new KeyParameter(kg.generateKey().getEncoded());
byte[] tweak = new byte[16];
TweakableBlockCipherParameters params = new TweakableBlockCipherParameters(key, tweak);
byte[] plaintext = "Hi! I'm cat!".getBytes();
byte[] ciphertext = encrypt(params, plaintext);
System.out.println(new String(decrypt(params, ciphertext)));
// prints "Hi! I'm cat!"
}
static byte[] encrypt(TweakableBlockCipherParameters params, byte[] plaintext) throws Exception {
return encryptOrDecrypt(true, params, plaintext);
}
static byte[] decrypt(TweakableBlockCipherParameters params, byte[] ciphertext) throws Exception {
return encryptOrDecrypt(false, params, ciphertext);
}
static byte[] encryptOrDecrypt(boolean encrypt, TweakableBlockCipherParameters params, byte[] bytes) throws Exception {
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
new CBCBlockCipher(
new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024)), new PKCS7Padding());
cipher.init(encrypt, params);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CipherOutputStream cos = new CipherOutputStream(baos, cipher);
cos.write(bytes);
// calling CipherOutputStream.close is mandatory
// it acts like Cipher.doFinal
cos.close();
return baos.toByteArray();
}
好的,那么使用轻量级API和计数器模式,这是最简单、最现代的模式之一:
public class BouncyEncrypt {
private static final int IV_SIZE = 16;
public static void main(String[] args) throws Exception {
// key should really consist of 16 random bytes
byte[] keyData = new byte[256 / Byte.SIZE];
KeyParameter key = new KeyParameter(keyData);
byte[] ciphertext = encryptWithAES_CTR(key, "owlstead");
System.out.println(decryptWithAES_CTR(key, ciphertext));
}
private static byte[] encryptWithAES_CTR(KeyParameter key, String in)
throws IllegalArgumentException, UnsupportedEncodingException,
DataLengthException {
// iv should be unique for each encryption with the same key
byte[] ivData = new byte[IV_SIZE];
SecureRandom rng = new SecureRandom();
rng.nextBytes(ivData);
ParametersWithIV iv = new ParametersWithIV(key, ivData);
SICBlockCipher aesCTR = new SICBlockCipher(new AESFastEngine());
aesCTR.init(true, iv);
byte[] plaintext = in.getBytes("UTF-8");
byte[] ciphertext = new byte[ivData.length + plaintext.length];
System.arraycopy(ivData, 0, ciphertext, 0, IV_SIZE);
aesCTR.processBytes(plaintext, 0, plaintext.length, ciphertext, IV_SIZE);
return ciphertext;
}
private static String decryptWithAES_CTR(KeyParameter key, byte[] ciphertext)
throws IllegalArgumentException, UnsupportedEncodingException,
DataLengthException {
if (ciphertext.length < IV_SIZE) {
throw new IllegalArgumentException("Ciphertext too short to contain IV");
}
ParametersWithIV iv = new ParametersWithIV(key, ciphertext, 0, IV_SIZE);
SICBlockCipher aesCTR = new SICBlockCipher(new AESFastEngine());
aesCTR.init(true, iv);
byte[] plaintext = new byte[ciphertext.length - IV_SIZE];
aesCTR.processBytes(ciphertext, IV_SIZE, plaintext.length, plaintext, 0);
return new String(plaintext, "UTF-8");
}
}
公共类弹跳加密{
专用静态最终int IV_尺寸=16;
公共静态void main(字符串[]args)引发异常{
//密钥实际上应该由16个随机字节组成
byte[]keyData=新字节[256/字节.SIZE];
KeyParameter key=新的KeyParameter(keyData);
byte[]ciphertext=encryptWithAES_CTR(密钥“owlstead”);
System.out.println(使用AES_CTR(密钥,密文)解密);
}
专用静态字节[]encryptWithAES\u CTR(键参数键,字符串输入)
抛出IllegalArgumentException、UnsupportedEncodingException、,
数据长度异常{
//对于使用相同密钥的每个加密,iv应该是唯一的
字节[]ivData=新字节[IV_大小];
SecureRandom rng=新的SecureRandom();
下一个字节(ivData);
参数swithiv=新参数swithiv(键,ivData);
SICBlockCipher aesCTR=新的SICBlockCipher(新的AESFastEngine());
aesCTR.init(真,iv);
字节[]明文=in.getBytes(“UTF-8”);
字节[]密文=新字节[ivData.length+明文.length];
System.arraycopy(ivData,0,密文,0,IV_大小);
aesCTR.processBytes(明文,0,明文.长度,密文,IV_大小);
返回密文;
}
使用AES_CTR(密钥参数密钥,字节[]密文)解密私有静态字符串
抛出IllegalArgumentException、UnsupportedEncodingException、,
数据长度异常{
if(密文长度
计数器模式不需要填充,并且完全在线,因此您只需调用processBytes
。对于CBC模式,您应该查看PaddedBufferedBlockCipher
。不过,在解密过程中,您仍然会有少量的缓冲区处理:在解密之前,您不知道存在的填充量
您可以删除IV代码和UTF-8字符解码+异常处理,但这将是不安全的,并且可能不兼容。这段代码将IV作为密文的前缀。不幸的是,我不得不使用实际的块密码对象。我试着这样做,但我无法将TweakableBlockCipherParams与“普通Java API”一起使用。我实际上也发布了一个关于这一点的问题:不幸的是,我不能使用这个,我被BouncyCastle的实现卡住了(请参阅对其他答案的评论)。@codebreaker我已经更新了我的答案,请看。请参阅