use*_*021 5 java size cryptography block
我正在制作一个加密某些文件的应用程序.我想使用gnu的cryptix库.它说它自2005年以来不再开发,但我想它拥有我需要的一切......我应该使用其他东西吗?
我有一个关于加密单个文件的问题.现在我用这样的循环来做:
for(int i=0; i+block_size < bdata.length; i += block_size)
cipher.encryptBlock(bdata, i, cdata, i);
Run Code Online (Sandbox Code Playgroud)
所以我的问题是如何加密可能与block_size不同的最后一个块.我想也许应该在最后一个块中添加一些额外的数据,但是我不知道如何解密...
我强烈建议使用AES加密,它也附带JAVA SDK.看看:使用AES和Java技术,它将为您提供一些很好的例子.要阅读有关AES的更多信息,请参阅:高级加密标准 - 维基百科.
切勿使用自己的加密方案或较旧形式的加密方案.AES已经在我们这个领域拥有更多知识的人进行了尝试和测试,所以你知道它会起作用.与您自己的或旧的加密方案一样,我们可能会错过致命的循环漏洞,这会使我们的数据受到攻击.
在这里看到这个问题,看看加密方案的不同之处:DES,Triple DES,AES,数据的河豚加密的比较
附录:
java中的AES可以完美地运行192和256位密钥,但您必须安装较新的JCE策略文件.看到这里和这里.您还应该将文件放在JDK中,否则从IDE执行时它不会起作用.
注意:确保下载正确的JCE策略文件,具体取决于您的Java版本,即1.4,1.5 1.6或7.
但是,如果使用128位密钥,则无需安装较新的JCE文件.
以下是java中使用CBC/AES/PKCS5Padding和随机IV使用的一些安全AES使用的模板RandomSecure.
请注意,您需要密钥和IV才能进行解密:
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* This program generates a AES key, retrieves its raw bytes, and then
* reinstantiates a AES key from the key bytes. The reinstantiated key is used
* to initialize a AES cipher for encryption and decryption.
*/
public class AES {
/**
* Encrypt a sample message using AES in CBC mode with a random IV genrated
* using SecyreRandom.
*
*/
public static void main(String[] args) {
try {
String message = "This string contains a secret message.";
System.out.println("Plaintext: " + message + "\n");
// generate a key
KeyGenerator keygen = KeyGenerator.getInstance("AES");
keygen.init(128); // To use 256 bit keys, you need the "unlimited strength" encryption policy files from Sun.
byte[] key = keygen.generateKey().getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
// build the initialization vector (randomly).
SecureRandom random = new SecureRandom();
byte iv[] = new byte[16];//generate random 16 byte IV AES is always 16bytes
random.nextBytes(iv);
IvParameterSpec ivspec = new IvParameterSpec(iv);
// initialize the cipher for encrypt mode
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);
System.out.println("Key: " + new String(key, "utf-8") + " This is important when decrypting");
System.out.println("IV: " + new String(iv, "utf-8") + " This is important when decrypting");
System.out.println();
// encrypt the message
byte[] encrypted = cipher.doFinal(message.getBytes());
System.out.println("Ciphertext: " + asHex(encrypted) + "\n");
// reinitialize the cipher for decryption
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivspec);
// decrypt the message
byte[] decrypted = cipher.doFinal(encrypted);
System.out.println("Plaintext: " + new String(decrypted) + "\n");
} catch (IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException | InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException | NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
/**
* Turns array of bytes into string
*
* @param buf Array of bytes to convert to hex string
* @return Generated hex string
*/
public static String asHex(byte buf[]) {
StringBuilder strbuf = new StringBuilder(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10) {
strbuf.append("0");
}
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
}
Run Code Online (Sandbox Code Playgroud)
我总是使用BouncyCastle
我还使用流式框架而不是您描述的for循环:它处理引发的问题.大多数情况下我使用它,因为当谈到加密(和线程)时,我很少相信自己的代码,我相信那些活着的人会吃掉它.这是我想要"gash"加密时使用的代码.即我没有特别的威胁模型,只想要"有点安全"的东西.
键的十六进制编码使它们更容易操作/存储等等.我使用"makeKey"来......好吧......制作一个密钥,然后我可以在加密和解密方法中使用密钥.显然,您可以使用byte[]而不是使用十六进制字符串作为键.
private static boolean initialised;
private static void init() {
if (initialised)
return;
Security.addProvider(new BouncyCastleProvider());
initialised = true;
}
public static String makeKey() {
init();
KeyGenerator generator = KeyGenerator.getInstance(algorithm, provider);
generator.init(keySize);
Key key = generator.generateKey();
byte[] encoded = key.getEncoded();
return Strings.toHex(encoded);
}
public static String aesDecrypt(String hexKey, String hexCoded) {
init();
SecretKeySpec key = new SecretKeySpec(Strings.fromHex(hexKey), algorithm);
Cipher cipher = Cipher.getInstance(algorithm + "/ECB/PKCS5Padding", provider);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] codedBytes = Strings.fromHex(hexCoded);
CipherInputStream inputStream = new CipherInputStream(new ByteArrayInputStream(codedBytes), cipher);
byte[] bytes = getBytes(inputStream, 256);
String result = new String(bytes, "UTF-8");
return result;
}
public static String aesEncrypt(String hexKey, String input) {
init();
SecretKeySpec key = new SecretKeySpec(Strings.fromHex(hexKey), algorithm);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, key);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(input.length());
CipherOutputStream outputStream = new CipherOutputStream(byteArrayOutputStream, cipher);
setText(outputStream, input);
byte[] outputBytes = byteArrayOutputStream.toByteArray();
String output = new String(Strings.toHex(outputBytes));
return output;
}
public static void setText(OutputStream outputStream, String text, String encoding) {
try {
outputStream.write(text.getBytes(encoding));
outputStream.flush();
} finally {
outputStream.close();
}
}
public static byte[] getBytes(InputStream inputStream, int bufferSize) {
try {
List<ByteArrayAndLength> list = Lists.newList();
while (true) {
byte[] buffer = new byte[bufferSize];
int count = inputStream.read(buffer);
if (count == -1) {
byte[] result = new byte[ByteArrayAndLength.length(list)];
int index = 0;
for (ByteArrayAndLength byteArrayAndLength : list) {
System.arraycopy(byteArrayAndLength.bytes, 0, result, index, byteArrayAndLength.length);
index += byteArrayAndLength.length;
}
assert index == result.length;
return result;
}
list.add(new ByteArrayAndLength(buffer, count));
}
} finally {
inputStream.close();
}
}
static class ByteArrayAndLength {
byte[] bytes;
int length;
public ByteArrayAndLength(byte[] bytes, int length) {
super();
this.bytes = bytes;
this.length = length;
}
static int length(List<ByteArrayAndLength> list) {
int result = 0;
for (ByteArrayAndLength byteArrayAndLength : list) {
result += byteArrayAndLength.length;
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
我已经删除了一些异常捕获以减少代码的大小,并将Strings.fromHex字符串转换回来byte[]
| 归档时间: |
|
| 查看次数: |
17964 次 |
| 最近记录: |