Java openssl加密/解密密钥生成

时间:2015-12-29 00:19:22

标签: java openssl cryptography aes sha256

我正在使用Java 8,并尝试使用Java模拟以下openssl调用。

加密

echo -n 'hello world' | openssl enc -a -aes-256-cbc -md sha256 -pass pass:97DE:4F76

  

U2FsdGVkX18PnO / NLSxJ1pg6OKoLyZApMz7aBRfKhJc =

解密:

echo U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc= | openssl enc -d -a -aes-256-cbc -md sha256 -pass pass:97DE:4F76

  

你好世界

问题:

  1. 我的实施不起作用。我已经访问了许多其他StackOverflow答案,但无法找到正确的实现。任何人都可以指出我正确的方向来解决这个问题吗?
  2. 上例中的openssl系统调用使用摘要sha256。如果我使用sha1而不是Java实现,那么只需要PBKDF2WithHmacSHA256更改PBKDF2WithHmacSHA1吗?
  3. Test.java

    package test;
    
    import java.security.spec.KeySpec;
    
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.PBEKeySpec;
    import javax.crypto.spec.SecretKeySpec;
    import javax.xml.bind.DatatypeConverter;
    
    public class Test {
    
        public static final String PASSWORD = "97DE:4F76";
    
        public static String encryptString(String clearText, String password) {
            return "";
        }
    
        // echo U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc= | openssl enc -d -a -aes-256-cbc -md sha256 -pass pass:97DE:4F76
        //
        // see https://stackoverflow.com/a/992413, https://stackoverflow.com/a/15595200,
        // https://stackoverflow.com/a/22445878, https://stackoverflow.com/a/11786924
        public static String decryptString(String cypherText, String password) {
            byte[] dataBase64 = DatatypeConverter.parseBase64Binary(cypherText);
            byte[] salt = {
                    (byte)0x0, (byte)0x0, (byte)0x0, (byte)0x0,
                    (byte)0x0, (byte)0x0, (byte)0x0, (byte)0x0
            };
    
            try {
                // generate the key
                SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); // "PBKDF2WithHmacSHA1"
                KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
                SecretKey tmp = factory.generateSecret(spec);
                SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
    
                // decrypt the message
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                byte[] iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
                cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
    
                byte[] decrypted = cipher.doFinal(dataBase64);
                String answer = new String(decrypted, "UTF-8");
                return answer;
    
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return "";
        }
    
        public static void main(String[] args) {
            System.out.println(decryptString("U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc=", PASSWORD));
        }
    }
    

    这是运行上述代码的当前输出:

    java.security.InvalidKeyException: Illegal key size     at
             javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)  at
             javax.crypto.Cipher.init(Cipher.java:1393)     at
             javax.crypto.Cipher.init(Cipher.java:1327)     at
             test.Test.decryptString(Test.java:42)  at
             test.Test.main(Test.java:55)
    

    更新: 这是我在使用此答案后最终实现的代码:https://stackoverflow.com/a/11786924 - >具有EVP_BytesToKey的其余常量和实现

    public static String decryptString(String cypherText, String password) {
            try {
                // decode the base64 cypherText into salt and encryptedString
                byte[] dataBase64 = DatatypeConverter.parseBase64Binary(cypherText);
                byte[] salt = Arrays.copyOfRange(dataBase64, SALT_OFFSET, SALT_OFFSET + SALT_SIZE);
                byte[] encrypted = Arrays.copyOfRange(dataBase64, CIPHERTEXT_OFFSET, dataBase64.length);
                System.out.println("dataBase64 = " + new String(dataBase64));
                System.out.println("salt: " + new BigInteger(1, salt).toString(16));
                System.out.println("encrypted: " + new BigInteger(1, encrypted).toString(16));    
    
                // --- specify cipher and digest for EVP_BytesToKey method ---
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                MessageDigest sha1 = MessageDigest.getInstance("SHA-256");
    
                // create key and IV
                final byte[][] keyAndIV = EVP_BytesToKey(
                        KEY_SIZE_BITS / Byte.SIZE,
                        cipher.getBlockSize(),
                        sha1,
                        salt,
                        password.getBytes("ASCII"),
                        ITERATIONS);
                SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES");
                IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]);
    
                // initialize the Encryption Mode
                cipher.init(Cipher.DECRYPT_MODE, key, iv);
    
                // decrypt the message
                byte[] decrypted = cipher.doFinal(encrypted);
                String answer = new String(decrypted, "UTF-8"); // should this be "ASCII"?
                return answer;
    
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return "";
        }
    

0 个答案:

没有答案