我一直在使用 Bouncy Castle API 为 byte[] 进行 PGP 加密和解密并收到 "Invalid Armor" 错误消息

I have been working on PGP Encrypt and Decrypt for byte[] with Bouncy Castle API and getting "Invalid Armor" error message

我在 Java 中使用充气城堡 API 开发 PGP Encryption/Decryption 有一段时间了,我成功地处理了文件,但我需要使用inputStream/byte 数组,我在这样做时遇到了问题。使用以下代码,加密工作没有任何问题。但是对于解密,我遇到了 "Invalid Armor" 错误,请参阅下面的错误消息。我搜索了整个 google,但在任何地方都找不到类似的错误。任何帮助将非常感激。让我知道我需要在我的代码中修复什么。我也在使用 PGPUtil class 到 convert/read public 和私钥。

错误:

Encryption Success
Exception in thread "main" java.io.IOException: invalid armor
    at org.bouncycastle.bcpg.ArmoredInputStream.readIgnoreSpace(Unknown Source)
    at org.bouncycastle.bcpg.ArmoredInputStream.read(Unknown Source)
    at org.bouncycastle.bcpg.BCPGInputStream.nextPacketTag(Unknown Source)
    at org.bouncycastle.openpgp.PGPObjectFactory.nextObject(Unknown Source)
    at com.iice.vega.unity.api.batch.pgp.PGPProcess.decrypt(PGPProcess.java:63)
    at com.iice.vega.unity.api.batch.pgp.PGPTest.main(PGPTest.java:64)

这是我的代码:

    public class PGPProcess {

    private static String publicKeyPath = System.getProperty("user.dir")+"/keys/Public_Key.asc";
    private static String privateKeyPath = System.getProperty("user.dir")+"/keys/Private_Key.asc";
    private static String password = "";

    public static byte[] decrypt(byte[] encrypted)
                    throws IOException, PGPException, NoSuchProviderException {
        Security.addProvider(new BouncyCastleProvider());
        InputStream keyIn = new BufferedInputStream(new FileInputStream(stsPrivateKeyPath));
        char[] password = "".toCharArray();
        InputStream in = new ByteArrayInputStream(encrypted);

        in = PGPUtil.getDecoderStream(in);

        JcaPGPObjectFactory        pgpF = new JcaPGPObjectFactory(in);
                        PGPEncryptedDataList    enc;
        Object o = pgpF.nextObject();


        if (o instanceof PGPEncryptedDataList) {
            enc = (PGPEncryptedDataList) o;
        } else {
            enc = (PGPEncryptedDataList) pgpF.nextObject();
        }


        Iterator it = enc.getEncryptedDataObjects();
        PGPPrivateKey sKey = null;
        PGPPublicKeyEncryptedData pbe = null;
        PGPSecretKeyRingCollection  pgpSec = new PGPSecretKeyRingCollection(
                                    PGPUtil.getDecoderStream(keyIn), new JcaKeyFingerprintCalculator());

        while (sKey == null && it.hasNext()) {
            pbe = (PGPPublicKeyEncryptedData) it.next();

            sKey = PGPExampleUtil.findSecretKey(pgpSec, pbe.getKeyID(), password);
        }

        if (sKey == null) {
            throw new IllegalArgumentException(
                            "secret key for message not found.");
        }
        InputStream clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(sKey));

        JcaPGPObjectFactory    plainFact = new JcaPGPObjectFactory(clear);

        PGPCompressedData   cData = (PGPCompressedData)plainFact.nextObject();

        JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(cData.getDataStream());

        PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();

        InputStream unc = ld.getInputStream();

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int ch;

        while ((ch = unc.read()) >= 0) {
            out.write(ch);
        }

        byte[] returnBytes = out.toByteArray();
        out.close();
        return returnBytes;
        }


    public static byte[] encrypt(byte[] clearData)
                    throws IOException, PGPException, NoSuchProviderException {



        Security.addProvider(new BouncyCastleProvider());
        String fileName=null;
        boolean withIntegrityCheck =true;
        boolean armor = false;

        if (fileName == null) {
            fileName = PGPLiteralData.CONSOLE;
        }
        PGPPublicKey encKey = PGPExampleUtil.readPublicKey(stsPublicKeyPath);

        ByteArrayOutputStream encOut = new ByteArrayOutputStream();

        OutputStream out = encOut;
        if (armor) {
            out = new ArmoredOutputStream(out);
        }

        ByteArrayOutputStream bOut = new ByteArrayOutputStream();

        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(
                                PGPCompressedData.ZIP);
        OutputStream cos = comData.open(bOut); // open it with the final
        // destination
        PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();


        OutputStream pOut = lData.open(cos, // the compressed output stream
                        PGPLiteralData.BINARY, fileName, // "filename" to store
                        clearData.length, // length of clear data
                        new Date() // current time
                        );
        pOut.write(clearData);

        lData.close();
        comData.close();

        PGPEncryptedDataGenerator   cPk = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC"));

        cPk.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider("BC"));

        byte[] bytes = bOut.toByteArray();

        OutputStream cOut = cPk.open(out, bytes.length);

        cOut.write(bytes); // obtain the actual bytes from the compressed stream

        cOut.close();

        out.close();

        return encOut.toByteArray();
    }
    }

有时从一组新的文件开始是很好的。在我的 GitHub-Repository 中 https://github.com/java-crypto/Whosebug/tree/master/PGP_Encrypt_Decrypt_Armor_Error 您可以下载 secret_rsa_kleo passphrase.zip 内容如下:

Main3.java: simple test program as shown below
PGPExampleUtil.java: taken from Bouncy Castle PGP examples
secret_rsa_kleo.asc: brandnew generated private key (done with Kleopatra 3.1.11)
pub_rsa_kleo.asc: public key
bcprov-jdk15to18-165.jar + bcpg-jdk15on-165.jar: Bouncy Castle jars

我用密码"mypassphrase"(没有“”:-)生成了我的密钥对。输出结果如下:

测试Java版本:11.0.6+8-b520.43 BouncyCastle版本:BC版本1.65

明文:54686973206973206d7920706c61696e74657874 解密文本:54686973206973206d7920706c61696e74657874 明文等于解密文本:true

ciphetext: 85010c03f9a05b3a12b538270107ff4c960552ca571ff4a24518189e038bd574e64504398b10fc85375e5f6b62ea3f69f686ebd20a1ef7cd0bd59823c025470d85930b89a5ee2c97683d39685c32a607f8c4ecb7a8270c4aff359f0b20a4e76599894f6d987c3d2d710e56a6354001fd4bfa54770609e917915dc51994feb49155a6b2259f3f1c449baca58e43440e6aee527f56cbbd024b463ec76dceab40ffbd940297115b93a535f00ca6c7880b449077d04e35ef1e2c35f579a4df8267be809c7ce5b82f627f1e4b45e9ae0cbd79f88d3c1621b45b6a7c527e86529480949fe9f69b31b79612a91248f2f5fad6750c46d2b4d025da9b70b18d3377938e73e4f941c969f722d2b2b21a44233cf5d24701a6363eb6e28a9b4c2431db135ff4be3423a5138f70aba971173d72df910b6a336c7f15158abcd7d40c2b491d4af7732de9b0783fc8887f9ca068d8274632a42fa876d0986208 密文字符串:����[:��8'��L��R��W��E����t��E9����7^kb��?i���� ������,��h=9h����취'J��5���e��Om�|=-qV��5@��K��Tw ��]������U ��%��?D����CDj�RV˽KF>��mΫ@����[��5��LjD��w��N5��,5��y��g����|��/bKE�� y����⊛L$1����4#��p��q=r��j3l����+IJ��s-��x?pos��h��'F2��/�� vИ

只需在您的原始系统上检查一件事:私钥取自此行:

String privateKeyPath = System.getProperty("user.dir")+"/keys/Private_Key.asc";

但在 encrypt/decrypt 方法中,变量是 stsPrivateKeyPath。

Main3.java:

import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;

import java.io.*;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;

public class Main3 {

    //private static String publicKeyPath = System.getProperty("user.dir")+"/keys/Public_Key.asc";
    private static String stsPublicKeyPath = "pub_rsa_kleo.asc";
    //private static String privateKeyPath = System.getProperty("user.dir")+"/keys/Private_Key.asc";
    private static String stsPrivateKeyPath = "secret_rsa_kleo.asc";
    private static String passwordString = "mypassphrase";

    public static void main(String[] args) throws NoSuchProviderException, IOException, PGPException {
        System.out.println("");
        Security.addProvider(new BouncyCastleProvider());
        System.out.println("\nTest with Java version: " + Runtime.version() + " BouncyCastle Version: " + Security.getProvider("BC") + "\n");

        byte[] plaintext = "This is my plaintext".getBytes("UTF-8");
        byte[] ciphertext = encrypt(plaintext);
        byte[] decryptedtext = decrypt(ciphertext);

        System.out.println("plaintext: " + bytesToHex(plaintext));
        System.out.println("decrytext: " + bytesToHex(decryptedtext));
        System.out.println("plaintext equals decryptedtext: " + Arrays.equals(plaintext, decryptedtext));

        System.out.println("\nciphetext: " + bytesToHex(ciphertext));
        System.out.println("ciphertext String: " + new String(ciphertext, "UTF-8"));

// bcprov-jdk15to18-165.jar
// bcpg-jdk15on-165.jar
// OpenJDK 11.0.5
    }

    public static byte[] decrypt(byte[] encrypted)
            throws IOException, PGPException, NoSuchProviderException {
        Security.addProvider(new BouncyCastleProvider());
        InputStream keyIn = new BufferedInputStream(new FileInputStream(stsPrivateKeyPath));
        char[] password = passwordString.toCharArray();
        //char[] password = "".toCharArray();
        InputStream in = new ByteArrayInputStream(encrypted);
        in = PGPUtil.getDecoderStream(in);
        JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);
        PGPEncryptedDataList enc;
        Object o = pgpF.nextObject();
        if (o instanceof PGPEncryptedDataList) {
            enc = (PGPEncryptedDataList) o;
        } else {
            enc = (PGPEncryptedDataList) pgpF.nextObject();
        }
        Iterator it = enc.getEncryptedDataObjects();
        PGPPrivateKey sKey = null;
        PGPPublicKeyEncryptedData pbe = null;
        PGPSecretKeyRingCollection  pgpSec = new PGPSecretKeyRingCollection(
                PGPUtil.getDecoderStream(keyIn), new JcaKeyFingerprintCalculator());
        while (sKey == null && it.hasNext()) {
            pbe = (PGPPublicKeyEncryptedData) it.next();
            sKey = PGPExampleUtil.findSecretKey(pgpSec, pbe.getKeyID(), password);
        }
        if (sKey == null) {
            throw new IllegalArgumentException(
                    "secret key for message not found.");
        }
        InputStream clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(sKey));
        JcaPGPObjectFactory    plainFact = new JcaPGPObjectFactory(clear);
        PGPCompressedData   cData = (PGPCompressedData)plainFact.nextObject();
        JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(cData.getDataStream());
        PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();
        InputStream unc = ld.getInputStream();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int ch;
        while ((ch = unc.read()) >= 0) {
            out.write(ch);
        }
        byte[] returnBytes = out.toByteArray();
        out.close();
        return returnBytes;
    }

    public static byte[] encrypt(byte[] clearData)
            throws IOException, PGPException {
        Security.addProvider(new BouncyCastleProvider());
        String fileName=null;
        boolean withIntegrityCheck = true;
        boolean armor = false; // org
        if (fileName == null) {
            fileName = PGPLiteralData.CONSOLE;
        }
        PGPPublicKey encKey = PGPExampleUtil.readPublicKey(stsPublicKeyPath);
        ByteArrayOutputStream encOut = new ByteArrayOutputStream();
        OutputStream out = encOut;
        if (armor) {
            out = new ArmoredOutputStream(out);
        }
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(
                PGPCompressedData.ZIP);
        OutputStream cos = comData.open(bOut); // open it with the final
        // destination
        PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();
        OutputStream pOut = lData.open(cos, // the compressed output stream
                PGPLiteralData.BINARY, fileName, // "filename" to store
                clearData.length, // length of clear data
                new Date() // current time
        );
        pOut.write(clearData);
        lData.close();
        comData.close();
        PGPEncryptedDataGenerator   cPk = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC"));
        cPk.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider("BC"));
        byte[] bytes = bOut.toByteArray();
        OutputStream cOut = cPk.open(out, bytes.length);
        cOut.write(bytes); // obtain the actual bytes from the compressed stream
        cOut.close();
        out.close();
        return encOut.toByteArray();
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuffer result = new StringBuffer();
        for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
        return result.toString();
    }
}

PGPExampleUtil.java

package PGP_Encrypt_Decrypt_Armor_Error;

import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;

import java.io.*;
import java.security.NoSuchProviderException;
import java.util.Iterator;

// https://github.com/bcgit/bc-java/blob/master/pg/src/main/java/org/bouncycastle/openpgp/examples/PGPExampleUtil.java
class PGPExampleUtil
{
    static byte[] compressFile(String fileName, int algorithm) throws IOException
    {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(algorithm);
        PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY,
                new File(fileName));
        comData.close();
        return bOut.toByteArray();
    }

    /**
     * Search a secret key ring collection for a secret key corresponding to keyID if it
     * exists.
     *
     * @param pgpSec a secret key ring collection.
     * @param keyID keyID we want.
     * @param pass passphrase to decrypt secret key with.
     * @return the private key.
     * @throws PGPException
     * @throws NoSuchProviderException
     */
    static PGPPrivateKey findSecretKey(PGPSecretKeyRingCollection pgpSec, long keyID, char[] pass)
            throws PGPException, NoSuchProviderException
    {
        PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);

        if (pgpSecKey == null)
        {
            return null;
        }

        return pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(pass));
    }

    static PGPPublicKey readPublicKey(String fileName) throws IOException, PGPException
    {
        InputStream keyIn = new BufferedInputStream(new FileInputStream(fileName));
        PGPPublicKey pubKey = readPublicKey(keyIn);
        keyIn.close();
        return pubKey;
    }

    /**
     * A simple routine that opens a key ring file and loads the first available key
     * suitable for encryption.
     *
     * @param input data stream containing the public key data
     * @return the first public key found.
     * @throws IOException
     * @throws PGPException
     */
    static PGPPublicKey readPublicKey(InputStream input) throws IOException, PGPException
    {
        PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(
                PGPUtil.getDecoderStream(input), new JcaKeyFingerprintCalculator());

        //
        // we just loop through the collection till we find a key suitable for encryption, in the real
        // world you would probably want to be a bit smarter about this.
        //

        Iterator keyRingIter = pgpPub.getKeyRings();
        while (keyRingIter.hasNext())
        {
            PGPPublicKeyRing keyRing = (PGPPublicKeyRing)keyRingIter.next();

            Iterator keyIter = keyRing.getPublicKeys();
            while (keyIter.hasNext())
            {
                PGPPublicKey key = (PGPPublicKey)keyIter.next();

                if (key.isEncryptionKey())
                {
                    return key;
                }
            }
        }

        throw new IllegalArgumentException("Can't find encryption key in key ring.");
    }

    static PGPSecretKey readSecretKey(String fileName) throws IOException, PGPException
    {
        InputStream keyIn = new BufferedInputStream(new FileInputStream(fileName));
        PGPSecretKey secKey = readSecretKey(keyIn);
        keyIn.close();
        return secKey;
    }

    /**
     * A simple routine that opens a key ring file and loads the first available key
     * suitable for signature generation.
     *
     * @param input stream to read the secret key ring collection from.
     * @return a secret key.
     * @throws IOException on a problem with using the input stream.
     * @throws PGPException if there is an issue parsing the input stream.
     */
    static PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException
    {
        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
                PGPUtil.getDecoderStream(input), new JcaKeyFingerprintCalculator());

        //
        // we just loop through the collection till we find a key suitable for encryption, in the real
        // world you would probably want to be a bit smarter about this.
        //

        Iterator keyRingIter = pgpSec.getKeyRings();
        while (keyRingIter.hasNext())
        {
            PGPSecretKeyRing keyRing = (PGPSecretKeyRing)keyRingIter.next();

            Iterator keyIter = keyRing.getSecretKeys();
            while (keyIter.hasNext())
            {
                PGPSecretKey key = (PGPSecretKey)keyIter.next();

                if (key.isSigningKey())
                {
                    return key;
                }
            }
        }

        throw new IllegalArgumentException("Can't find signing key in key ring.");
    }
}

secret_rsa_kleo.asc:

-----BEGIN PGP PRIVATE KEY BLOCK-----

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
=eGJl
-----END PGP PRIVATE KEY BLOCK-----

pub_rsa_kleo.asc:

-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBF7hImoBCAC1YHtHUokERd9OqXiB0/ncVwQaqEBLdd3cxRZ0Kyd7K+OxHH5f
VCdYRWSyVANn4Z+3JjDGZFC5eAUFGWSMwVnWB6VlIW6+7UegGA2cIUAyH6fzBogs
W4hhoIVhUHXTsbUpqj2bhWj85db3GNuSnIhyu6ed0AavsnBbDooHFJYOYgXOvNqN
pq1gjbLIHvBZXZg/OvrpjSM0GoLX6bIDxofzh3ktFlBkUP1fGJ/Cx1xu1ANZ6mQq
6VF8DMcYBO08+HiQvaRkOYYI20AR5X3BOYA+UR63CiXjfvt9r2OX+GTExe3XJp8U
wkvm14JRCyad42ADOkik8fdiy4rGy0yVwe/BABEBAAG0GHRlc3QgdGVzdCA8dGVz
dEB0ZXN0LmRlPokBVAQTAQgAPhYhBOtbtDyOZRSPL5sgGfmgWzoStTgnBQJe4SJq
AhsDBQkDwfO2BQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEPmgWzoStTgnc2UH
/2cLGLIAQke/VT/Humfx0CwK9dHMgXT+BS52G43C8dzfTp1iwn31t/B/rfh9fDEx
uYT+nratO6hROME8ZzHcm6pLpyH4ZJCb35UO0KA/Eo8TN56VM69pEPzQbpc80AiF
gAQ0tLm58dAFIkMahKPfcOp5YpIw1wrfxiJkygV7e37wh9wiah/w2ho/8BawYEUG
arjoB13fYB5gNLzsmk1nd+/nMOZDaqOJXl3GhVI9i1pS5cqkT/T9WquybqW73whI
LpsSdBu9MWihhedCx6KtoDpSPrtzzXjKc7PJIjBPDN4pzH/0fqvN/k2736P1MP5z
yq/nOMOTevV6YZtN9SXA6Hq5AQ0EXuEiagEIAMN3rP9PhOm0ho14SXwjXKF/vXc+
EDT+vglwg7bZUpsJMYt5TMnT6dNHlV/ek8oMUEvBqBIHWrUplG/LFyaNJAjmgE4q
FoNHy1V9H9Jw439PH1T/8Mbw/n/k3xvanWcl03QcRcvPag8oaczYO+/+cbyl0R/X
lk2lAlBomfnM2+nfUFyTKVXJoG7TSHNRGbG3jmKyVzPi3Tb/JqbW2ITUBKkd+J6h
l5EK9NExqyXVoFHUf2KWfawXzEw9Dk83fKoDQHQkknzdQ+vm4l6MQ9m40OV7U3xd
6yd49p8h1+jpYv4bWguiWiJquAosABOF5DunpIUWel82uZ/PRCuLZpbGG38AEQEA
AYkBPAQYAQgAJhYhBOtbtDyOZRSPL5sgGfmgWzoStTgnBQJe4SJqAhsMBQkDwfO2
AAoJEPmgWzoStTgnFZ0H/3y9RhcPK65ssKjclr4gwMyquaDPqwKuXJLEZZNuapj0
G7j4AKJX6bN/RYJ3Nw51iC3vv5j5Pd4l6/d5PwZN5t54SV+T+6WPCbfbvBGn+jwj
mcE584hfwndioXjE+dVVoX4dhwkfZLOz6t825UTpKp2XEoFOeVpjTN8NhdiN5xe6
UHEUyHFBCkP9g81j1nKbgXXB6kss5r59WMIZrasVNOzh8WnAVLrTkuQC+/KZZqwi
8dseaBEeCR5vSzCZWjJULSeziiOGChn+e8CNKpgEn2QuNsWoOoaPe6wQVRoY/oxV
t4wc4dVh2W0HjzMOveo3Dvw66QT1NfXx4cmaOm5HWhc=
=bgyD
-----END PGP PUBLIC KEY BLOCK-----

"Invalid Armor"

此错误可能由于多种情况而发生。这是我的经历: 我格式化了键[加入行]而不是我应该按原样使用键。

密钥应始终采用以下文本格式。

AhsDBQkDwfO2BQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEPmgWzoStTgnc2UH /2cLGLIAQke/VT/Humfx0CwK9dHMgXT+BS52G43C8dzfTp1iwn31t/B/rfh9fDEx uYT+nratO6hROME8ZzHcm6pLpyH4ZJCb35UO0KA/Eo8TN56VM69pEPzQbpc80AiF gAQ0tLm58dAFIkMahKPfcOp5YpIw1wrfxiJkygV7e37wh9wiah/w2ho/8BawYEUG