【问题标题】:encrypt in Android and decrypt in CryptoJS在 Android 中加密并在 CryptoJS 中解密
【发布时间】:2017-12-10 17:44:55
【问题描述】:

您好,我有 java 代码可以解密使用 CryptoJS 库 (AES) 加密的密文。 现在我想编写将再次加密明文的javacode。

请找到下面的代码。

 try {
        String secret = "René Über";
        String cipherText="U2FsdGVkX1+tsmZvCEFa/iGeSA0K7gvgs9KXeZKwbCDNCs2zPo+BXjvKYLrJutMK+hxTwl/hyaQLOaD7LLIRo2I5fyeRMPnroo6k8N9uwKk=";

        byte[] cipherData = Base64.decode(cipherText, Base64.DEFAULT);
        byte[] saltData = Arrays.copyOfRange(cipherData, 8, 16);

        MessageDigest md5 = MessageDigest.getInstance("MD5");
        final byte[][] keyAndIV = GenerateKeyAndIV(32, 16, 1, saltData, secret.getBytes("utf-8"), md5);
        SecretKeySpec key = new SecretKeySpec(keyAndIV[0], "AES");
        IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);

        byte[] encrypted = Arrays.copyOfRange(cipherData, 16, cipherData.length);
        Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
        aesCBC.init(Cipher.DECRYPT_MODE, key, iv);
        byte[] decryptedData = aesCBC.doFinal(encrypted);
        String decryptedText = new String(decryptedData,"utf-8");
        System.out.println("Decrypted "+decryptedText);
//Here I get right plain text as 
//System.out: Decrypted The quick brown fox jumps over the lazy dog.


        Cipher abc=Cipher.getInstance("AES/CBC/PKCS5Padding");
        abc.init(Cipher.ENCRYPT_MODE,key,iv);
        byte[] encryptedData=abc.doFinal(decryptedData);
        String str=Base64.encodeToString(encryptedData,Base64.DEFAULT);


        System.out.println("encrypted "+str);

//Here i want the encrypted text as
// encrypted U2FsdGVkX1+tsmZvCEFa/iGeSA0K7gvgs9KXeZKwbCDNCs2zPo+BXjvKYLrJutMK+hxTwl/hy//aQLOaD7LLIRo2I5fyeRMPnroo6k8N9uwKk=
//but i receive 
//System.out: encrypted IZ5IDQruC+Cz0pd5krBsIM0KzbM+j4FeO8pgusm60wr6HFPCX+HJpAs5oPssshGjYjl/J5Ew+//eui



    }catch (Exception e)
    {}

当我解密代码时,我得到了正确的纯文本,但是当我再次加密纯文本时,我没有像以前那样得到加密的文本。 请帮忙。

GenerateKeyAndIV 函数代码:-

 public static byte[][] GenerateKeyAndIV(int keyLength, int ivLength, int iterations, byte[] salt, byte[] password, MessageDigest md) {

    int digestLength = md.getDigestLength();
    int requiredLength = (keyLength + ivLength + digestLength - 1) / digestLength * digestLength;
    byte[] generatedData = new byte[requiredLength];
    int generatedLength = 0;

    try {
        md.reset();

        // Repeat process until sufficient data has been generated
        while (generatedLength < keyLength + ivLength) {

            // Digest data (last digest if available, password data, salt if available)
            if (generatedLength > 0)
                md.update(generatedData, generatedLength - digestLength, digestLength);
            md.update(password);
            if (salt != null)
                md.update(salt, 0, 8);
            md.digest(generatedData, generatedLength, digestLength);

            // additional rounds
            for (int i = 1; i < iterations; i++) {
                md.update(generatedData, generatedLength, digestLength);
                md.digest(generatedData, generatedLength, digestLength);
            }

            generatedLength += digestLength;
        }

        // Copy key and IV into separate byte arrays
        byte[][] result = new byte[2][];
        result[0] = Arrays.copyOfRange(generatedData, 0, keyLength);
        if (ivLength > 0)
            result[1] = Arrays.copyOfRange(generatedData, keyLength, keyLength + ivLength);

        return result;

    } catch (DigestException e) {
        throw new RuntimeException(e);

    } finally {
        // Clean out temporary data
        Arrays.fill(generatedData, (byte)0);
    }
}

【问题讨论】:

  • 是的,它是来自stackoverflow.com/questions/41432896/… 的复制粘贴,我对密码学不太熟悉。该链接帮助我完美解密密文。但现在我陷入了加密
  • 您已经表示要学习加密货币。但我建议您现在使用更高级别的 API。他们的想法是使用加密来确保您的系统安全,而不仅仅是让您的代码正常工作。
  • 感谢您的建议。 @Maarten Bodewes。我将学习加密来使用它,而不仅仅是代码工作。
  • 警告给其他读者:虽然上面的代码在试图模仿 OpenSSL 的意义上是正确的,但迭代次数是 1,这意味着基于密码的密钥派生功能并不像通常应该的那样安全。此代码还缺少消息身份验证,并且容易受到填充 oracle 攻击,如果适用。现在 OpenSSL 命令行也可以使用 PBKDF2 指定迭代次数。

标签: java android encryption cryptography aes


【解决方案1】:

您的密文开头有“Salted__”,解密时会跳过。如果要创建与 OpenSSL 兼容的密文,则需要在加密模式中添加相同的前缀。

当您在 base64 到十六进制解码器中查看时,您的加密代码密文似乎是正确的,例如提供here的那个。但是,因为每个字符只包含 64 位,并且由于字节已经移动了 16 个位置(不能被 3 整除),所以它只是表明你的整个密文不正确,而它只是在前面缺少 16 个字节。

【讨论】:

  • 感谢您的宝贵时间。我需要更多学习才能理解你的答案。我不熟悉密码学。我使用这个库解决了我的问题。 github.com/evgenyneu/aes-crypto-android。我从android调用了cryptojs javascript加密/解密函数。
  • @Jayshree:你能告诉我你最后是如何使用 javascript 文件加密的吗?
  • @Animesh Jena :- 我用下面的链接github.com/evgenyneu/aes-crypto-android
【解决方案2】:

在这里发布我的 android 工作代码,我在服务器上使用加密进行解密。下面的代码是使用 AES 算法

  private static final String key = "aesExamplekey";
  private static final String initVector = "exampleintvec";

public static String encrypt(String value) {
    try {
        IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

        byte[] encrypted = cipher.doFinal(value.getBytes());

       // byte[] finalCiphertext = new byte[encrypted.length+2*16];
          return Base64.encodeToString(encrypted, Base64.NO_WRAP);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return null;
}`

服务器端代码 asp.net

        public string DecryptStringAES(string cipherText)
    {
        //  var keybytes = Encoding.UTF8.GetBytes("7061737323313233");
        //  var iv = Encoding.UTF8.GetBytes("7061737323313233");
        var keybytes = Encoding.UTF8.GetBytes("aesExamplekey");
        var iv = Encoding.UTF8.GetBytes("exampleintvec");

        var encrypted = Convert.FromBase64String(cipherText);
        var decriptedFromJavascript = DecryptStringFromBytes(encrypted, keybytes, iv);
        return string.Format(decriptedFromJavascript);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 2016-08-22
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多