【问题标题】:Java : how to create java.security.Key from .asc file?Java:如何从 .asc 文件创建 java.security.Key?
【发布时间】:2016-10-04 19:52:51
【问题描述】:

我必须将文件加密为 pgp 格式。我有 .asc 格式的公钥

cipher init() 方法需要传入一个公钥。使用文件创建该密钥的方法是什么。就我而言,它是 .asc 文件。

    Cipher cipher;
    Key publicKey = null;

    try 
    {
        cipher = Cipher.getInstance("RSA", "BC");




    } catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException e) {
        String msg = "failed to create output stream";
        LOGGER.error( msg, e );
        throw new RuntimeException( msg, e );
    }

    try {
        publicKey = getPublicKey(publicKeyPath);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    try {
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return ( new CipherOutputStream(outputStream, cipher));

我收到错误: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: 无效的密钥格式

我的 getPublicKey 方法看起来像(但我认为,我不必这样做,因为文件本身具有公钥)

public static PublicKey getPublicKey(String filename)
        throws Exception {

        byte[] keyBytes = Files.readAllBytes(new File(filename).toPath());

        X509EncodedKeySpec spec =
          new X509EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
      } 

Public_key.asc 看起来像:

            -----BEGIN PGP PUBLIC KEY BLOCK-----
            Version: Encryption Desktop 10.3.2 (Build 16127)

            mQENBFYhXNoBCACgX/u03wm8cLqmTZiKGx6H/1ZUoBsfaDB2rdG2D8jYQzvaq4MA
            hZWBEVhA2BGKrNI+a2SDhKGAY4OK7aUZVAVG1bfQNVdNe80TbEF8g/wO2FreYPkb
            ojPtkwgyzsvb1BKwgRM1UMjkM5OWnhAPDhFDc39SFbmHLsXrURqFqJd9T3xzF6ty

            ................................................................


            D4WXvHpPXCJcwCBe+/81ZpjxlrLkUu8bO79jxZdKcI5ZRpmIe/VPJoDUVKLvl9n3
            ANvDJGdGcW3x6RyL9QOnoRDf6njimqcTm8UqImdLCz4TFdv94dvM4K0NOWuFdYal
            E9Q+U0Q7aiaWn+Kt+OYpd6++m7wnJRH/q0H69LIR9v3Td3udzOaxv/gzXF1BFuAS
            DQs6iA==
            =ckOV
            -----END PGP PUBLIC KEY BLOCK-----

以下是此键的属性:

【问题讨论】:

  • 您不能将公钥与 AES 一起使用。 AES 是具有 128、192 或 256 位随机密钥的对称密码。公钥是 RSA、EC 或其他非对称算法。就像把电池扔进油箱一样。
  • 您需要特殊的 PGP 密钥加载器,因为 X.509 在密钥格式方面与 PGP 不兼容。
  • 为什么不使用 Bouncy Castle 中的 PGP 功能?
  • 我使用 org.bouncycastle.openpgp* lib 来实现这个,在我用 10GB 文件进行加密/解密测试之前,它工作得非常好。由于此 api 在压缩/解压缩后将数据保存在内存中,因此我们看到 java 堆空间错误是大文件的结果。
  • 我认为 Maarten 提议使用 BouncyCastle 来加载密钥(这是您所要求的)。之后,您可以使用 BouncyCastle 的 JcaPGPKeyConverter 从中制作 java.security.PublicKey/PrivateKey 并将其用于您想要的任何东西。

标签: java cryptography public-key


【解决方案1】:

Robert 和 Maarten Bodewes 的回复是可行的方法之一。

我的公钥在 .asc 文件中,私钥在 .skr 中(密钥环)

我以这种方式实现了它,它对我有用:

                public static PublicKey getPublicKey(
                    String filePath)
                    throws PGPException, NoSuchProviderException, FileNotFoundException, IOException
                {
                    PGPPublicKey    encKey = readPublicKey(new FileInputStream(filePath));
                    return new JcaPGPKeyConverter().setProvider("BC").getPublicKey(encKey);
                }




                public static PrivateKey getPrivateKey( 
                        InputStream    in, char[]      passwd) 
                        throws IOException, PGPException, NoSuchProviderException 
                    { 
                        in = PGPUtil.getDecoderStream(in); 

                        PGPSecretKeyRingCollection        pgpSec = new PGPSecretKeyRingCollection(in); 

                        // 
                        // 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. 
                        // 

                        // 
                        // iterate through the key rings. 
                        // 
                        Iterator<?> rIt = pgpSec.getKeyRings(); 

                        while (rIt.hasNext()) 
                        { 
                            PGPSecretKeyRing    kRing = (PGPSecretKeyRing)rIt.next();     
                            Iterator<?>                        kIt = kRing.getSecretKeys(); 

                            while (kIt.hasNext()) 
                            { 
                                PGPSecretKey    k = (PGPSecretKey)kIt.next(); 

                                if (k != null) 
                                { 
                                    PGPPrivateKey pk = k.extractPrivateKey(passwd, "BC"); 
                                     return new JcaPGPKeyConverter().setProvider("BC").getPrivateKey(pk);
                                } 
                            } 
                        } 

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

                public static PGPPublicKey readPublicKey( 
                        InputStream    in) 
                        throws IOException, PGPException 
                    { 
                        in = PGPUtil.getDecoderStream(in); 

                        PGPPublicKeyRingCollection        pgpPub = new PGPPublicKeyRingCollection(in); 

                        // 
                        // 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. 
                        // 

                        // 
                        // iterate through the key rings. 
                        // 
                        Iterator<?> rIt = pgpPub.getKeyRings(); 

                        while (rIt.hasNext()) 
                        { 
                            PGPPublicKeyRing    kRing = (PGPPublicKeyRing)rIt.next();     
                            Iterator<?>                        kIt = kRing.getPublicKeys(); 

                            while (kIt.hasNext()) 
                            { 
                                PGPPublicKey    k = (PGPPublicKey)kIt.next(); 

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

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

【讨论】:

  • 你用过什么赏金堡提供者?,你介意提供maven依赖
猜你喜欢
  • 1970-01-01
  • 2012-06-28
  • 2013-10-13
  • 1970-01-01
  • 2015-04-24
  • 1970-01-01
  • 2010-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多