InvalidKeyException:非法的密钥大小

时间:2013-08-29 21:27:22

标签: java cryptography

在将此标记为重复之前,请阅读完整的问题。

我在这里看了很多关于这个问题的问题,每个答案都说要安装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();
}

1 个答案:

答案 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);
}