代码之家  ›  专栏  ›  技术社区  ›  gmmo

java.lang.IllegalArgumentException:解密字符串时错误的base-64

  •  4
  • gmmo  · 技术社区  · 9 年前

    我试图使用密钥库对字符串进行加密,并将本文用作参考。

    KeyPairGeneratorSpec replacement with KeyGenParameterSpec.Builder equivalents - Keystore operation failed

    然而,当我解密字符串时,我总是得到这个“坏的base-64”。我不清楚如何解决这个问题。我知道加密字符串包含解密器不知道的字符。但我不明白这个问题。

    我看到了一些类似的帖子,但没有太大帮助,因为答案上没有代码。

    java.lang.IllegalArgumentException: bad base-64

    这是我的测试代码的片段,有人能告诉我如何解压字符串吗?

    Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
    inCipher.init(Cipher.ENCRYPT_MODE, publicKey);
    
    Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
    outCipher.init(Cipher.DECRYPT_MODE, privateKey);
    
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    CipherOutputStream cipherOutputStream = new CipherOutputStream(
            outputStream, inCipher);
    cipherOutputStream.write(plainText.getBytes("UTF-8"));
    cipherOutputStream.close();
    
    String ecryptedText = outputStream.toString();
    Log.d(TAG, "Encrypt = " + ecryptedText);
    
    String cipherText = ecryptedText;
    CipherInputStream cipherInputStream = new CipherInputStream(
            new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher);
    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");
    Log.d(TAG, "Decrypt = " + ecryptedText);
    
    1 回复  |  直到 8 年前
        1
  •  2
  •   Christos Lytras    9 年前

    下面是一个关于如何使用 安卓 KeyStore 使用加密/解密内存字符串 ByteArrayOutputStream ByteArrayInputStream .注意提供者的更改,对于 >= 6 "AndroidKeyStoreBCWorkaround" 对于旧版本,请使用 "AndroidOpenSSL" Base64.encodeToString 这样地:

    String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
    

    我的最后一个工作示例基于您的代码

    try {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
                KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
        keyPairGenerator.initialize(
                new KeyGenParameterSpec.Builder(
                        "key1",
                        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                        .build());
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
    
        // error in android 6: InvalidKeyException: Need RSA private or public key AndroidOpenSSL
        // error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround
        String provider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? "AndroidOpenSSL" : "AndroidKeyStoreBCWorkaround";
    
        Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
        inCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
    
        Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
        outCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
    
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        CipherOutputStream cipherOutputStream = new CipherOutputStream(
                outputStream, inCipher);
    
        String plainText = "This is a text";
    
        cipherOutputStream.write(plainText.getBytes("UTF-8"));
        cipherOutputStream.close();
    
        String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
        Log.d(TAG, "Encrypt = " + ecryptedText);
    
        String cipherText = ecryptedText;
        CipherInputStream cipherInputStream = new CipherInputStream(
                new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher);
    
        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");
        Log.d(TAG, "Decrypt = " + finalText);
    } catch (javax.crypto.NoSuchPaddingException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (IOException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (NoSuchAlgorithmException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (NoSuchProviderException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (InvalidAlgorithmParameterException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (InvalidKeyException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (UnsupportedOperationException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    }
    

    产出

    D/MainActivity: Encrypt = rejkfeas3HgYnZOlC4S/R3KvlMTyiBjr5T6LqWGj9bq6nvpM0KBsoeYtr4OdCLITFX5GojuO4VpB
                    Hy11n8zc9JcAx4IFW0Aw0/DfCmMDvIomQItBAaIWewZqNHc0UwS0y/JRhAe8SiTz5sFJ6Abvgax6
                    vEfbYT0gzok+qtlfBNQLPvXejquhc0pZBaX1RgKDZyEJh3DBVRaFDgogK8XphaI/xtd1Cww9uO63
                    QxA7HfrFUN8rJXrHF4EMi/yrDxs2xVHGF0v21xeuXRwLW9JXYn4fFAJJ0Jr8N5f03UDuKeNlI568
                    RFVOGH7WpOLvKN4CDlsC+DT4Z8YVIOdtS/tO+Q==
    D/MainActivity: Decrypt = This is a text
    

    Android Studio Output

    更新

    对于 Android API 19 ,您只需使用上一个 密钥库 美国石油学会 KeyPairGeneratorSpec KeyGenParameterSpec 这样地:

    try {
        Calendar start = Calendar.getInstance();
        Calendar end = Calendar.getInstance();
        end.add(Calendar.YEAR, 1);
    
        KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this)
            .setAlias("key1")
            .setSubject(new X500Principal("CN=Sample Name, O=Android Authority"))
            .setSerialNumber(BigInteger.ONE)
            .setStartDate(start.getTime())
            .setEndDate(end.getTime())
            .build();
    
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
        generator.initialize(spec);
    
        // error in android 6: InvalidKeyException: Need RSA private or public key AndroidOpenSSL
        // error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround
        String provider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? "AndroidOpenSSL" : "AndroidKeyStoreBCWorkaround";
    
        KeyPair keyPair = generator.generateKeyPair();
    
        Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
        inCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
    
        Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
        outCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
    
    
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        CipherOutputStream cipherOutputStream = new CipherOutputStream(
                outputStream, inCipher);
    
        String plainText = "This is a text";
    
        cipherOutputStream.write(plainText.getBytes("UTF-8"));
        cipherOutputStream.close();
    
        String ecryptedText = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
        Log.d(TAG, "Encrypt = " + ecryptedText);
    
        String cipherText = ecryptedText;
        CipherInputStream cipherInputStream = new CipherInputStream(
                new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), outCipher);
    
        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");
        Log.d(TAG, "Decrypt = " + finalText);
    } catch (javax.crypto.NoSuchPaddingException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (IOException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (NoSuchAlgorithmException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (NoSuchProviderException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (InvalidAlgorithmParameterException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (InvalidKeyException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (UnsupportedOperationException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    }
    
    推荐文章