如何使用bouncycastle opengpg encryptFile,签名和解密

时间:2015-01-23 06:57:30

标签: java android encryption bouncycastle

首先,请原谅我的英语水平不高。感谢您的解决方案!

我是bouncycastle的新手。我已经使用它来创建PGPkeypair,获取PGPPublickKey和secretKey。我也使用secretKey来加密txt文件,但是我无法对其进行签名和解密。我的代码几乎来自于org.bouncycastle.openpgp.example我不知道问题出在哪里 这是我的代码:

1,创建PGPKeyPair并获取PGPPublickey,secretKey并保存它们:

public static PGPPublicKey generateKeyPair() throws Exception {

    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", "BC");
    keyGen.initialize(1024, new SecureRandom());
    int algorithm = PGPPublicKey.RSA_GENERAL;
    PGPKeyPair pkp=new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date());


    Security.addProvider(new BouncyCastleProvider());
    Security.addProvider(new BouncyCastlePQCProvider());
    // 生成RSA密钥对
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
    kpg.initialize(4096);
    KeyPair kp = kpg.generateKeyPair();
    // 转为PGP密钥对
    JcaPGPKeyPair pgpKeyPair = new JcaPGPKeyPair(PGPPublicKey.RSA_GENERAL,
            kp, new Date());
    // 用户标识一般使用email
    String identity = "fad@163.com";
    // 用来保护密钥的密码
    char[] passPhrase = "123456".toCharArray();
    PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
            .build().get(HashAlgorithmTags.SHA1);
    PGPContentSignerBuilder certSignerBuilder = new JcaPGPContentSignerBuilder(
            pgpKeyPair.getPublicKey().getAlgorithm(),
            HashAlgorithmTags.SHA1);
    PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
            SymmetricKeyAlgorithmTags.AES_256, sha1Calc,0x90).setProvider("BC").build(
            passPhrase);
    // 生成PGP密钥
    PGPSecretKey secretKey = new PGPSecretKey(
            PGPSignature.DEFAULT_CERTIFICATION, pgpKeyPair, identity,
            sha1Calc, null, null, certSignerBuilder, keyEncryptor);

    // 保存PGP密钥到asc文件
    File externalStorageDirectory = Environment
            .getExternalStorageDirectory();
    String path = externalStorageDirectory.toString();
    OutputStream secretOut = new ArmoredOutputStream(new FileOutputStream(
            path + "/SecretKey.asc"));
    secretKey.encode(secretOut);
    secretOut.close();
    // 保存PGP公钥到asc文件
    OutputStream publicOut = new ArmoredOutputStream(new FileOutputStream(
            path + "/PublicKey.asc"));
    PGPPublicKey key = secretKey.getPublicKey();
    key.encode(publicOut);
    publicOut.close();
    return key;
}

2,使用SignedFileProcessor.java加密文件和解密文件:

public class KeyBasedLargeFileProcessor{
public static void decryptFile(
    String inputFileName,
    String keyFileName,
    char[] passwd,
    String defaultFileName)
    throws IOException, NoSuchProviderException
{
    InputStream in = new BufferedInputStream(new FileInputStream(inputFileName));
    InputStream keyIn = new BufferedInputStream(new                                         FileInputStream(keyFileName));
    decryptFile(in, keyIn, passwd, defaultFileName);
    keyIn.close();
    in.close();
}

/**
 * decrypt the passed in message stream
 */
public static void decryptFile(
    InputStream in,
    InputStream keyIn,
    char[]      passwd,
    String      defaultFileName)
    throws IOException, NoSuchProviderException
{    
    in = PGPUtil.getDecoderStream(in);

    try
    {
        PGPObjectFactory        pgpF = new PGPObjectFactory(in);
        PGPEncryptedDataList    enc;

        Object                  o = pgpF.nextObject();
        //
        // the first object might be a PGP marker packet.
        //
        if (o instanceof PGPEncryptedDataList)
        {
            enc = (PGPEncryptedDataList)o;
        }
        else
        {
            enc = (PGPEncryptedDataList)pgpF.nextObject();
        }

        //
        // find the secret key
        //
        Iterator                    it = enc.getEncryptedDataObjects();
        PGPPrivateKey               sKey = null;
        PGPPublicKeyEncryptedData   pbe = null;
        PGPSecretKeyRingCollection  pgpSec = new PGPSecretKeyRingCollection(
            PGPUtil.getDecoderStream(keyIn));                                                                 

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

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

        if (sKey == null)
        {
            throw new IllegalArgumentException("secret key for message not found.");
        }

        InputStream         clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(sKey));

        PGPObjectFactory    plainFact = new PGPObjectFactory(clear);

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

        InputStream         compressedStream = new BufferedInputStream(cData.getDataStream());
        PGPObjectFactory    pgpFact = new PGPObjectFactory(compressedStream);

        Object              message = pgpFact.nextObject();

        if (message instanceof PGPLiteralData)
        {
            PGPLiteralData ld = (PGPLiteralData)message;

            String outFileName = ld.getFileName();
            if (outFileName.length() == 0)
            {
                outFileName = defaultFileName;
            }

            InputStream unc = ld.getInputStream();
            OutputStream fOut =  new BufferedOutputStream(new FileOutputStream(outFileName));

            Streams.pipeAll(unc, fOut);

            fOut.close();
        }
        else if (message instanceof PGPOnePassSignatureList)
        {
            throw new PGPException("encrypted message contains a signed message - not literal data.");
        }
        else
        {
            throw new PGPException("message is not a simple encrypted file - type unknown.");
        }

        if (pbe.isIntegrityProtected())
        {
            if (!pbe.verify())
            {
                System.err.println("message failed integrity check");
            }
            else
            {
                System.err.println("message integrity check passed");
            }
        }
        else
        {
            System.err.println("no message integrity check");
        }
    }
    catch (PGPException e)
    {
        System.err.println(e);
        if (e.getUnderlyingException() != null)
        {
            e.getUnderlyingException().printStackTrace();
        }
    }
}

public static void encryptFile(
    String          outputFileName,
    String          inputFileName,
    String          encKeyFileName,
    boolean         armor,
    boolean         withIntegrityCheck)
    throws IOException, NoSuchProviderException, PGPException
{
    OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFileName));
    PGPPublicKey encKey = PGPExampleUtil.readPublicKey(encKeyFileName);
    encryptFile(out, inputFileName, encKey, armor, withIntegrityCheck);
    out.close();
}

public static void encryptFile(
    OutputStream    out,
    String          fileName,
    PGPPublicKey    encKey,
    boolean         armor,
    boolean         withIntegrityCheck)
    throws IOException, NoSuchProviderException
{    
    if (armor)
    {
        out = new ArmoredOutputStream(out);
    }

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

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

        OutputStream                cOut = cPk.open(out, new byte[1 << 16]);

        PGPCompressedDataGenerator  comData = new PGPCompressedDataGenerator(
                                                                PGPCompressedData.ZIP);

        PGPUtil.writeFileToLiteralData(comData.open(cOut), PGPLiteralData.BINARY, new File(fileName), new byte[1 << 16]);

        comData.close();

        cOut.close();

        if (armor)
        {
            out.close();
        }
    }
    catch (PGPException e)
    {
        System.err.println(e);
        if (e.getUnderlyingException() != null)
        {
            e.getUnderlyingException().printStackTrace();
        }
    }
}

}

3,这是我的测试代码:     private void test(){

    File storageDirectory = Environment.getExternalStorageDirectory();
    final String opath = storageDirectory.toString();
    final File publcKeyFile = new File(storageDirectory, "PublicKey.asc");
    if(!publcKeyFile.exists()){
        try {
            OpenGPGUtil.generateKeyPair();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }else {
        System.out.println("密钥存在");
    }
    final File secretKeyFile = new File(storageDirectory, "SecretKey.asc");
    final File enFile = new File(storageDirectory, "s.txt");
    final File file = new File(storageDirectory, "x.txt");
    final File deFile = new File(storageDirectory, "ss.txt");
    final String publcKeyfilePath = publcKeyFile.toString();
    final String secretKeyFilePath = secretKeyFile.toString();
    final String enFilePath = enFile.toString();
    final String filePath = file.toString();
    final String deFilePath = deFile.toString();

    new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                KeyBasedLargeFileProcessor.encryptFile(enFilePath,
                        filePath, publcKeyfilePath, true, true);
//                  KeyBasedLargeFileProcessor.decryptFile(enFilePath,
//                          secretKeyFilePath, "123456".toCharArray(),
//                          deFilePath);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }).start();
}

以下是三行注释,如果我删除它们,Eclipse的logcat将显示:

/System.err(7498): java.io.FileNotFoundException: 
/x.txt: open failed: EROFS (Read-only file system)
System.err(7498):   at libcore.io.IoBridge.open(IoBridge.java:409)
System.err(7498):   at java.io.FileOutputStream
<init(FileOutputStream.java:88)
System.err(7498):   at java.io.FileOutputStream
.<init> (FileOutputStream.java:128)
System.err(7498):   at java.io.FileOutputStream
.<init>(FileOutputStream.java:117)
System.err(7498):   at com.example.opengpgs.KeyBasedLargeFileProcessor.
decryptFile(KeyBasedLargeFileProcessor.java:147)
System.err(7498):   at  com.example.opengpgs.KeyBasedLargeFileProcessor
.decryptFile(KeyBasedLargeFileProcessor.java:69)
System.err(7498):   at com.example.opengpgs.MainActivity$1.
run(MainActivity.java:62)
System.err(7498):   at java.lang.Thread.run(Thread.java:841)
System.err(7498): Caused by: libcore.io.ErrnoException: 
open failed:  EROFS (Read-only file system)
System.err(7498):   at libcore.io.Posix.open(Native Method)
System.err(7498):   at libcore.io.BlockGuardOs.
open(BlockGuardOs.java:110)
System.err(7498):   at libcore.io.IoBridge.open(IoBridge.java:393)
System.err(7498):   ... 7 more
IInputConnectionWrapper(7498): getCursorCapsMode on 
inactive   InputConnection

1 个答案:

答案 0 :(得分:1)

从错误来看,您的文件系统似乎是只读的,但您正在尝试将其写入文件x.txt