在将此标记为重复之前,请阅读完整的问题。
我在这里看了很多关于这个问题的问题,每个答案都说要安装JCE。但是,如果我想将程序发送给其他人,另一台计算机,几乎任何开发计算机以外的任何计算机,他们也必须安装JCE。
有没有办法可以使用更小的密钥而无需安装任何东西?
我的加密方法;
public static String encrypt(String in) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException, IOException {
String out = " ";
// generate a key
KeyGenerator keygen = KeyGenerator.getInstance("AES");
keygen.init(128);
byte[] key = keygen.generateKey().getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
// build the initialization vector
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);
saveKey(key, iv); //<-- save to file
// initialize the cipher for encrypt mode
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);
byte[] encrypted = cipher.doFinal(in.getBytes());
out = asHex(encrypted);
return out;
}
我的解密方法:
public static String decrypt(String in) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException, IOException, KeyFileNotFoundException, UnknownKeyException {
String out = " ";
byte[] key = readKey("key").clone(); //<--from file
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
byte[] iv = readKey("iv"); //<-- from file
IvParameterSpec ivspec = new IvParameterSpec(iv);
//initialize the cipher for decryption
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivspec);
// decrypt the message
byte[] decrypted = cipher.doFinal(in.getBytes());
out = asHex(decrypted);
return out;
}
我的saveKey()方法:
private static void saveKey(byte[] key, byte[] iv) throws FileNotFoundException, IOException {
File keyFile = new File(Logging.getCurrentDir() + "\\cikey.key");
keys.setProperty("key", asHex(key));
keys.setProperty("iv", asHex(iv));
keys.store(new FileOutputStream(keyFile.getAbsolutePath(), false), null);
}
我的readKey()方法:
private static byte[] readKey(String request) throws KeyFileNotFoundException, UnknownKeyException, FileNotFoundException, IOException {
File keyFile = new File(Logging.getCurrentDir() + "\\cikey.key");
byte[] storage;
keys.load(new FileInputStream(keyFile));
if (!keyFile.exists())
throw new KeyFileNotFoundException("Key file not located.");
if (keys.containsKey(request) == false)
throw new UnknownKeyException("Key not found.");
else
storage = keys.getProperty(request).getBytes();
return storage;
}
asHex()方法(将数组传递给String):
public static String asHex(byte buf[]) {
StringBuilder strbuf = new StringBuilder(buf.length * 2);
for (int 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();
}
答案 0 :(得分:3)
有没有办法可以使用更小的密钥而无需安装任何东西?
您不能使用密钥大小小于128位的AES,但还有其他密码可用:DES,Blowfish等。它们不如AES安全,但如果您的应用程序仍然可以做到这一点(如大多数应用程序都不值得复杂的黑客努力。这是56位DES的示例:
public static String encrypt(String in) throws Exception {
String out = " ";
// generate a key
KeyGenerator keygen = KeyGenerator.getInstance("DES");
keygen.init(56);
byte[] key = keygen.generateKey().getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(key, "DES");
// build the initialization vector
SecureRandom random = new SecureRandom();
byte iv[] = new byte[8]; //generate random 8 byte IV.
random.nextBytes(iv);
IvParameterSpec ivspec = new IvParameterSpec(iv);
// initialize the cipher for encrypt mode
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);
byte[] encrypted = cipher.doFinal(in.getBytes());
out = asHex(encrypted);
return out;
}
在代码中存储和读取密钥也存在问题。您将它们存储为十六进制,但从默认平台编码中读取为符号。以下是如何使两个操作均匀的示例:
private static void saveKey(byte[] key, byte[] iv) throws IOException {
File keyFile = new File("C:/cikey.key");
keys.setProperty("key", toHexString(key));
keys.setProperty("iv", toHexString(iv));
keys.store(new FileOutputStream(keyFile.getAbsolutePath(), false), null);
}
private static byte[] readKey(String request) throws IOException {
File keyFile = new File("C:/cikey.key");
keys.load(new FileInputStream(keyFile));
return toByteArray(keys.getProperty(request));
}
public static String toHexString(byte[] array) {
return DatatypeConverter.printHexBinary(array);
}
public static byte[] toByteArray(String s) {
return DatatypeConverter.parseHexBinary(s);
}