Android将PGP集成到项目中

 雅芳07866 发布于 2023-02-02 19:03

我对PGP及其工作方式非常熟悉.我想在一个项目中包含一些功能,但到目前为止,我的研究让我头疼.我想做的是创建一个带有已定义私有密码短语的公钥.从那里,我将与某人共享公钥,然后他们可以使用密钥加密消息并将其返回给我可以解密的地方.我设想代码看起来像这样.

要生成我的私有pgp密钥:

PGPKey key = new PGPKey();
key.setPassPhrase("MySecretPassword!!!1");
key.generateRandomSharedKey();
key.build();

要加密,我会将我的共享密钥提供给朋友:

String encryptedText = PGPTools.Encrypt("Text to encrypt", getSharedKey());

要在发送给我之后解密加密的字符串:

String decryptedText = PGPTools.Decrypt(encryptedText, key, "MySecretPassword!!!1")

显然我知道我正在跳过大量的细节.通过我的研究,我看到了对诸如Bouncy Castle和Spongy Castle等图书馆的引用.任何帮助将非常感谢!

1 个回答
  • 我想发布我的解决方案,因为A.这很难让这个工作,并且B.如果任何加密专业人员想要审核我的代码,我将永远感激.

    我包括以下4个库:

    compile 'com.madgag.spongycastle:core:1.50.0.0'
    compile 'com.madgag.spongycastle:pg:1.50.0.0'
    compile 'com.madgag.spongycastle:pkix:1.50.0.0'
    compile 'com.madgag.spongycastle:prov:1.50.0.0'
    

    需要添加Bouncy Castle作为安全提供程序.我将此代码包含在一个类中,该类在应用程序加载时初始化其他一些对象.

    static {
        Security.addProvider(new BouncyCastleProvider());
    }
    

    这是我创建的utils类,它实际上包含了一些细节.稍微编辑:

    import com.example.Device;
    
    import org.spongycastle.bcpg.ArmoredInputStream;
    import org.spongycastle.bcpg.ArmoredOutputStream;
    import org.spongycastle.bcpg.HashAlgorithmTags;
    import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
    import org.spongycastle.bcpg.sig.Features;
    import org.spongycastle.bcpg.sig.KeyFlags;
    import org.spongycastle.crypto.generators.RSAKeyPairGenerator;
    import org.spongycastle.crypto.params.RSAKeyGenerationParameters;
    import org.spongycastle.openpgp.PGPCompressedData;
    import org.spongycastle.openpgp.PGPCompressedDataGenerator;
    import org.spongycastle.openpgp.PGPEncryptedData;
    import org.spongycastle.openpgp.PGPEncryptedDataGenerator;
    import org.spongycastle.openpgp.PGPEncryptedDataList;
    import org.spongycastle.openpgp.PGPException;
    import org.spongycastle.openpgp.PGPKeyPair;
    import org.spongycastle.openpgp.PGPKeyRingGenerator;
    import org.spongycastle.openpgp.PGPLiteralData;
    import org.spongycastle.openpgp.PGPLiteralDataGenerator;
    import org.spongycastle.openpgp.PGPObjectFactory;
    import org.spongycastle.openpgp.PGPPrivateKey;
    import org.spongycastle.openpgp.PGPPublicKey;
    import org.spongycastle.openpgp.PGPPublicKeyEncryptedData;
    import org.spongycastle.openpgp.PGPPublicKeyRing;
    import org.spongycastle.openpgp.PGPSecretKey;
    import org.spongycastle.openpgp.PGPSecretKeyRing;
    import org.spongycastle.openpgp.PGPSignature;
    import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
    import org.spongycastle.openpgp.PGPUtil;
    import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
    import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
    import org.spongycastle.openpgp.operator.PGPDigestCalculator;
    import org.spongycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
    import org.spongycastle.openpgp.operator.bc.BcPBESecretKeyEncryptorBuilder;
    import org.spongycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
    import org.spongycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
    import org.spongycastle.openpgp.operator.bc.BcPGPKeyPair;
    import org.spongycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory;
    import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
    import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.math.BigInteger;
    import java.nio.charset.Charset;
    import java.security.SecureRandom;
    import java.util.Date;
    import java.util.Iterator;
    
    public class PgpUtils {
        private static final String PROVIDER = "SC";
        private static final String KEY_RING_ID = "asdf@asdf.com";
    
        public static String decrypt(String encryptedText, String password) throws Exception {
            byte[] encrypted = encryptedText.getBytes();
            InputStream in = new ByteArrayInputStream(encrypted);
            in = PGPUtil.getDecoderStream(in);
            PGPObjectFactory pgpF = new PGPObjectFactory(in);
            PGPEncryptedDataList enc;
            Object o = pgpF.nextObject();
            if (o instanceof PGPEncryptedDataList) {
                enc = (PGPEncryptedDataList) o;
            } else {
                enc = (PGPEncryptedDataList) pgpF.nextObject();
            }
            PGPPrivateKey sKey = null;
            PGPPublicKeyEncryptedData pbe = null;
            while (sKey == null && enc.getEncryptedDataObjects().hasNext()) {
                pbe = (PGPPublicKeyEncryptedData)enc.getEncryptedDataObjects().next();
                sKey = getPrivateKey(getPGPSecretKeyRing(), pbe.getKeyID(), password.toCharArray());
            }
            if (pbe != null) {
                InputStream clear = pbe.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey));
                PGPObjectFactory pgpFact = new PGPObjectFactory(clear);
                PGPCompressedData cData = (PGPCompressedData) pgpFact.nextObject();
                pgpFact = new PGPObjectFactory(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 new String(returnBytes);
            }
            return null;
        }
    
        private static PGPPublicKey getPublicKey(PGPPublicKeyRing publicKeyRing) {
            Iterator<?> kIt = publicKeyRing.getPublicKeys();
            while (kIt.hasNext()) {
                PGPPublicKey k = (PGPPublicKey) kIt.next();
                if (k.isEncryptionKey()) {
                    return k;
                }
            }
            return null;
        }
    
        private static PGPPrivateKey getPrivateKey(PGPSecretKeyRing keyRing, long keyID, char[] pass) throws PGPException {
            PGPSecretKey secretKey = keyRing.getSecretKey(keyID);
            PBESecretKeyDecryptor decryptor = new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass);
            return secretKey.extractPrivateKey(decryptor);
        }
    
        public static String encrypt(String msgText) throws IOException, PGPException {
            byte[] clearData = msgText.getBytes();
            PGPPublicKey encKey = getPublicKey(getPGPPublicKeyRing());
            ByteArrayOutputStream encOut = new ByteArrayOutputStream();
            OutputStream out = new ArmoredOutputStream(encOut);
            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
            PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedDataGenerator.ZIP);
            OutputStream cos = comData.open(bOut);
            PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();
            OutputStream pOut = lData.open(cos, PGPLiteralData.BINARY, PGPLiteralData.CONSOLE, clearData.length, new Date());
            pOut.write(clearData);
            lData.close();
            comData.close();
            PGPEncryptedDataGenerator encGen =
                    new PGPEncryptedDataGenerator(
                            new JcePGPDataEncryptorBuilder(PGPEncryptedData.AES_256).setWithIntegrityPacket(true).setSecureRandom(
                                    new SecureRandom()).setProvider(PROVIDER));
            if (encKey != null) {
                encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider(PROVIDER));
                byte[] bytes = bOut.toByteArray();
                OutputStream cOut = encGen.open(out, bytes.length);
                cOut.write(bytes);
                cOut.close();
            }
            out.close();
            return new String(encOut.toByteArray());
        }
    
        public final static PGPKeyRingGenerator generateKeyRingGenerator (char[] pass) throws PGPException{
            RSAKeyPairGenerator kpg = new RSAKeyPairGenerator();
            kpg.init(new RSAKeyGenerationParameters(BigInteger.valueOf(0x10001), new SecureRandom(), 2048, 12));
            PGPKeyPair rsakp_sign = new BcPGPKeyPair(PGPPublicKey.RSA_SIGN, kpg.generateKeyPair(), new Date());
            PGPKeyPair rsakp_enc = new BcPGPKeyPair(PGPPublicKey.RSA_ENCRYPT, kpg.generateKeyPair(), new Date());
            PGPSignatureSubpacketGenerator signhashgen = new PGPSignatureSubpacketGenerator();
            signhashgen.setKeyFlags(false, KeyFlags.SIGN_DATA|KeyFlags.CERTIFY_OTHER|KeyFlags.SHARED);
            signhashgen.setPreferredSymmetricAlgorithms(false, new int[]{SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192, SymmetricKeyAlgorithmTags.AES_128});
            signhashgen.setPreferredHashAlgorithms(false, new int[]{HashAlgorithmTags.SHA256, HashAlgorithmTags.SHA1, HashAlgorithmTags.SHA384, HashAlgorithmTags.SHA512, HashAlgorithmTags.SHA224});
            signhashgen.setFeature(false, Features.FEATURE_MODIFICATION_DETECTION);
            PGPSignatureSubpacketGenerator enchashgen = new PGPSignatureSubpacketGenerator();
            enchashgen.setKeyFlags(false, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE);
            PGPDigestCalculator sha1Calc = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA1);
            PGPDigestCalculator sha256Calc = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA256);
            PBESecretKeyEncryptor pske = (new BcPBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256, sha256Calc, 0xc0)).build(pass);
            PGPKeyRingGenerator keyRingGen = new PGPKeyRingGenerator (PGPSignature.POSITIVE_CERTIFICATION, rsakp_sign,
                    KEY_RING_ID, sha1Calc, signhashgen.generate(), null, new BcPGPContentSignerBuilder(rsakp_sign.getPublicKey().getAlgorithm(),
                    HashAlgorithmTags.SHA1), pske);
            keyRingGen.addSubKey(rsakp_enc, enchashgen.generate(), null);
            return keyRingGen;
        }
    
        private static PGPPublicKeyRing getPGPPublicKeyRing() throws IOException {
            ArmoredInputStream ais = new ArmoredInputStream(new ByteArrayInputStream(Device.getDevice().getPgpPublicKey().getBytes()));
            return (PGPPublicKeyRing) new PGPObjectFactory(ais).nextObject();
        }
    
        private static PGPSecretKeyRing getPGPSecretKeyRing() throws IOException {
            ArmoredInputStream ais = new ArmoredInputStream(new ByteArrayInputStream(Device.getDevice().getPgpSecretKey().getBytes()));
            return (PGPSecretKeyRing) new PGPObjectFactory(ais).nextObject();
        }
    
        public final static String genPGPPublicKey (PGPKeyRingGenerator krgen) throws IOException {
            ByteArrayOutputStream baosPkr = new ByteArrayOutputStream();
            PGPPublicKeyRing pkr = krgen.generatePublicKeyRing();
            ArmoredOutputStream armoredStreamPkr = new ArmoredOutputStream(baosPkr);
            pkr.encode(armoredStreamPkr);
            armoredStreamPkr.close();
            return new String(baosPkr.toByteArray(), Charset.defaultCharset());
        }
    
        public final static String genPGPPrivKey (PGPKeyRingGenerator krgen) throws IOException {
            ByteArrayOutputStream baosPriv = new ByteArrayOutputStream ();
            PGPSecretKeyRing skr = krgen.generateSecretKeyRing();
            ArmoredOutputStream armoredStreamPriv = new ArmoredOutputStream(baosPriv);
            skr.encode(armoredStreamPriv);
            armoredStreamPriv.close();
            return new String(baosPriv.toByteArray(), Charset.defaultCharset());
        }
    }
    

    以下是我创建私钥和公钥的方法:

    final PGPKeyRingGenerator krgen = PgpUtils.generateKeyRingGenerator("password".toCharArray());
    String pgpPublicKey = PgpUtils.genPGPPublicKey(krgen);
    String pgpSecretKey = PgpUtils.genPGPPrivKey(krgen);
    

    最后使用您自己的公钥加密和解密:

    String encrypted = PgpUtils.encrypt("message text");
    String decrypted = PgpUtils.decrypt(encrypted, "Password");
    

    2023-02-02 19:06 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有