首页 > 解决方案 > Android 传递 IV 参数加密/解密文本

问题描述

我希望你能帮助我关联我的代码。

我试图将参数 IV 传递给加密/解密

加密功能:

我尝试连接文本;四

encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT) + ";" + (Base64.encodeToString(encryptionIv, Base64.DEFAULT)));

我认为这很好,如图所示。

 public void encryptString(String alias) {
        try {

            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
            String initialText = startText.getText().toString();
            if(initialText.isEmpty()) {
                Toast.makeText(this, "Enter text in the 'Initial Text'", Toast.LENGTH_LONG).show();
                return;
            }
            Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");

            inCipher.init(Cipher.ENCRYPT_MODE, secretKey);

            byte[] src= initialText.getBytes("UTF-8");

            byte[] iv = inCipher.getIV();
            assert iv.length == 12;
            byte[] cipherText = inCipher.doFinal(src);
            assert cipherText.length == src.length + 16;
            byte[] message = new byte[12 + src.length + 16];
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            CipherOutputStream cipherOutputStream = new CipherOutputStream(
                    outputStream, inCipher);
            cipherOutputStream.write(src);
            cipherOutputStream.close();
            byte [] vals = outputStream.toByteArray();
            encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT));
        } catch (Exception e) {
            Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

[![在此处输入图像描述][1]][1] 你能帮我举个例子来让解密工作正常吗?

谢谢你的帮助

更新:您好,我试图通过 IV 作为示例:

我的代码在这里:

 public void encryptString(String alias) {
        try {
            KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
            RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();

            String initialText = startText.getText().toString();
            if(initialText.isEmpty()) {
                Toast.makeText(this, "Enter text in the 'Initial Text' widget", Toast.LENGTH_LONG).show();
                return;
            }

            Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
            inCipher.init(Cipher.ENCRYPT_MODE, publicKey);

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            CipherOutputStream cipherOutputStream = new CipherOutputStream(
                    outputStream, inCipher);
            cipherOutputStream.write(initialText.getBytes("UTF-8"));
            cipherOutputStream.close();

            byte [] vals = outputStream.toByteArray();
            encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT));
        } catch (Exception e) {
            Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

[![在此处输入图像描述][2]][2]

新更新:

加密代码

public void encryptString(String alias) {
        try {

            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
            String initialText = startText.getText().toString();
            if(initialText.isEmpty()) {
                Toast.makeText(this, "Enter text in the 'Initial Text'", Toast.LENGTH_LONG).show();
                return;
            }
            Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");

            inCipher.init(Cipher.ENCRYPT_MODE, secretKey);

            byte[] src= initialText.getBytes("UTF-8");
            byte[] iv = inCipher.getIV();
            assert iv.length == 12;
            byte[] cipherText = inCipher.doFinal(src);
            assert cipherText.length == src.length + 16;
            byte[] message = new byte[12 + src.length + 16];
            System.arraycopy(iv, 0, message, 0, 12);
            System.arraycopy(cipherText, 0, message, 12, cipherText.length);
            //ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            //CipherOutputStream cipherOutputStream = new CipherOutputStream(
              //      outputStream, inCipher);
            //cipherOutputStream.write(message);
            //cipherOutputStream.close();
            //byte [] vals = outputStream.toByteArray();
            encryptedText.setText(Base64.encodeToString(message, Base64.DEFAULT));
        } catch (Exception e) {
            Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

解密代码:(不工作)

public void decryptString(String alias) {
        try {

            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
            String cipherText = encryptedText.getText().toString();

            byte[] src = cipherText.getBytes();
            byte[] message = new byte[12 + src.length + 16];
            Cipher output = Cipher.getInstance("AES/GCM/NoPadding");
            GCMParameterSpec params = new GCMParameterSpec(128, message, 0, 12);
            output.init(Cipher.DECRYPT_MODE, secretKey, params);
          //  output.doFinal(message, 12, message.length - 12);



            CipherInputStream cipherInputStream = new CipherInputStream(
             new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), output);
            ArrayList<Byte> values = new ArrayList<>();
           int nextByte;
           while ((nextByte = cipherInputStream.read()) != -1) {
                values.add((byte)nextByte);
            }

          byte[] bytes = new byte[values.size()];
         for(int i = 0; i < bytes.length; i++) {
            bytes[i] = values.get(i).byteValue();
         }

            String finalText = new String(bytes, 0, bytes.length, "UTF-8");
            decryptedText.setText(finalText);

        } catch (Exception e) {
            Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

你能帮我解决图像中显示的错误吗?

[![在此处输入图像描述][3]][3]

<<---更新的解决方案-->

加密函数:

 public void encryptString(String alias) {
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
            String initialText = startText.getText().toString();
            if(initialText.isEmpty()) {
                Toast.makeText(this, "Enter text in the 'Initial Text'", Toast.LENGTH_LONG).show();
                return;
            }
            Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");
            inCipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] src= initialText.getBytes("UTF-8");
            byte[] iv = inCipher.getIV();
            assert iv.length == 12;
            byte[] cipherText = inCipher.doFinal(src);
            assert cipherText.length == src.length + 16;
            byte[] message = new byte[12 + src.length + 16];
            System.arraycopy(iv, 0, message, 0, 12);
            System.arraycopy(cipherText, 0, message, 12, cipherText.length);
            encryptedText.setText(Base64.encodeToString(message, Base64.DEFAULT));
        } catch (Exception e) {
            Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

解密功能:

    public void decryptString(String alias) {
        try {

            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
            String cipherText = encryptedText.getText().toString();
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            byte[] nonceCiphertextTag = Base64.decode(cipherText, Base64.DEFAULT);
            GCMParameterSpec params = new GCMParameterSpec(128, nonceCiphertextTag, 0, 12);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, params);
            byte[] decrypted = cipher.doFinal(nonceCiphertextTag, 12, nonceCiphertextTag.length - 12);
            String finalText = new String(decrypted, 0, decrypted.length, "UTF-8");
            decryptedText.setText(finalText);
        } catch (Exception e) {
            Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

非常感谢@Topaco 的帮助

标签: androidencryptionaes-gcm

解决方案


在最新发布的加密代码中,将nonce、密文和标签串联起来并进行Base64编码,以下称为nonceCiphertextTagB64.

解密时

  • nonceCiphertextTagB64必须首先被 Base64 解码为nonceCiphertextTag,
  • nonce 必须封装在一个GCMParameterSpec实例中;nonce 是 的前 12 个字节nonceCiphertextTag
  • AES/GCM/NoPadding必须创建一个密码实例,它使用密钥和GCMParameterSpec解密模式的实例进行初始化,
  • 密文和标签的连接被解密;密文和标签的连接是nonce之后的数据。

在以下示例实现中,对于 repro,使用 32 字节的密钥01234567890123456789012345678901(而不是密钥库中的密钥)。密文是使用发布的加密代码创建的,使用相同的密钥和明文快速棕色狐狸跳过懒狗

...
String nonceCiphertextTagB64 =
        "UpyxMnzPrw+zJGANL4wBbaC+UX5KnMKYwhR0u2iF/GDCcU38YKWlvJp1zJ+mrN0POP7lz9y+eweH\n" +
        "vIxAH4R4U3At8T0fVe0=";
SecretKeySpec secretKey = new SecretKeySpec("01234567890123456789012345678901".getBytes(StandardCharsets.UTF_8),"AES");
byte[] nonceCiphertextTag = Base64.decode(nonceCiphertextTagB64, Base64.DEFAULT);
GCMParameterSpec params = new GCMParameterSpec(128, nonceCiphertextTag, 0, 12);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, params);
byte[] decrypted = cipher.doFinal(nonceCiphertextTag, 12, nonceCiphertextTag.length - 12);
System.out.println(new String(decrypted, StandardCharsets.UTF_8)); // The quick brown fox jumps over the lazy dog
... 

输出是:

The quick brown fox jumps over the lazy dog

推荐阅读