Java: как создать java.security.Ключ из файла .asc?

#java #cryptography #public-key

#java #криптография #открытый ключ

Вопрос:

Я должен зашифровать файл в формате 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-----
  

Вот свойства этого ключа:

введите описание изображения здесь

Комментарии:

1. Вы не можете использовать открытый ключ с AES. AES — это симметричный шифр со случайным ключом 128, 192 или 256 бит. Открытый ключ — это RSA, EC или другой асимметричный алгоритм. Как сбрасывать батарейки в бензобак.

2. Вам нужен специальный загрузчик ключей PGP, потому что X.509 несовместим с PGP в отношении формата ключа.

3. Почему бы не использовать функциональность PGP в Bouncy Castle?

4. Я использовал org.bouncycastle.openpgp * lib для реализации этого, который работал отлично, пока я не протестировал файл объемом 10 ГБ для шифрования / дешифрования. Поскольку этот api хранит данные в памяти после сжатия / де-сжатия, мы увидели ошибку java heap space в результате с большим файлом.

5. Я думаю, что Маартен предлагал использовать BouncyCastle для загрузки ключа (о чем вы просили). После этого вы можете использовать BouncyCastle JcaPGPKeyConverter для создания java.security. Извлеките из него PublicKey / PrivateKey и используйте его для чего угодно.

Ответ №1:

Ответ от Роберта и Мартена Бодевеса — один из способов.

Мой открытый ключ был в файле .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."); 
                    } 
  

Комментарии:

1. какой поставщик bountycastle вы использовали?, не могли бы вы предоставить зависимость maven