Spongy Castle - problem z generowaniem kluczy

0

Witam.
Jestem w trakcie pisania aplikacji do generowania kluczy publicznych i prywatnych oraz szyfrowania wiadomości.
Do tego celu wykorzystałem bibliotekę Spongy Castle https://rtyley.github.io/spongycastle/.
Problem polega na tym, że klucze są błędnie generowane. Gdy chcę nimi zaszyfrować jakąś wiadomość to dostaję komunikat o błędzie:
"Can't use an RSA_SIGN key for encryption". Próbowałem również zaimportować je w gpg na komputerze i widać, że brakuje "uid" (screen niżej, pierwszy klucz jest poprawny)
title
Przy próbie szyfrowania wiadomości w na kompie gpg wyświetla komunikat: "ten klucz jest bezużyteczny".
Poniżej zamieszczam kod, który użyłem do generowania kluczy:

public final PGPKeyRingGenerator genRsaKeyRing(String id, char[] pass) {
    try {
        RSAKeyPairGenerator kpg = new RSAKeyPairGenerator();

        // RSA KeyGen parameters
        BigInteger publicExponent = BigInteger.valueOf(0x10001);
        int certainty = 12;
        RSAKeyGenerationParameters rsaKeyGenerationParameters = new RSAKeyGenerationParameters(publicExponent, new SecureRandom(), secpar, certainty);
        kpg.init(rsaKeyGenerationParameters);

        // generate master key (signing) and subkey (enc)
        Date now = new Date();
        PGPKeyPair kpSign = new BcPGPKeyPair(PGPPublicKey.RSA_SIGN, kpg.generateKeyPair(), now);
        PGPKeyPair kpEnc = new BcPGPKeyPair(PGPPublicKey.RSA_ENCRYPT, kpg.generateKeyPair(), now);

        // sign the master key packet
        PGPSignatureSubpacketGenerator signSigPacket = new PGPSignatureSubpacketGenerator();

        // metadata for master key
        boolean isCritical = true;
        int keyPurpose = KeyFlags.SIGN_DATA | KeyFlags.CERTIFY_OTHER;
        signSigPacket.setKeyFlags(isCritical, keyPurpose);

        int[] symAlgos = new int[] {SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192, SymmetricKeyAlgorithmTags.BLOWFISH, SymmetricKeyAlgorithmTags.CAST5};
        signSigPacket.setPreferredSymmetricAlgorithms(isCritical, symAlgos);

        int[] hashAlgos = new int[] {HashAlgorithmTags.SHA512, HashAlgorithmTags.SHA384, HashAlgorithmTags.SHA256};
        signSigPacket.setPreferredHashAlgorithms(isCritical, hashAlgos);

        signSigPacket.setFeature(isCritical, Features.FEATURE_MODIFICATION_DETECTION);

        // sign encryption subkey
        PGPSignatureSubpacketGenerator signEncPacket = new PGPSignatureSubpacketGenerator();

        // metadata for subkey
        keyPurpose = KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE;
        signEncPacket.setKeyFlags(isCritical, keyPurpose);


        // digests
        PGPDigestCalculator digest1 = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA1);
        PGPDigestCalculator digest256 = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA256);

        // encryption for secret key
        PBESecretKeyEncryptor pske = (new BcPBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256, digest256, pwdCount)).build(pass);

        //  create the keyring
        BcPGPContentSignerBuilder contentSignerBuilder = new BcPGPContentSignerBuilder(kpSign.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA256);
        rsaKr = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, kpSign, id, digest1, signSigPacket.generate(), null, contentSignerBuilder, pske);

        // encryption subkey
        rsaKr.addSubKey(kpEnc, signEncPacket.generate(), null);
    } catch (PGPException e){
        e.printStackTrace();
    }
    return rsaKr;
} 
 public void writeKeys(){
        String iconsStoragePath = Environment.getExternalStorageDirectory() + "/myKeys2/";
        File sdIconStorageDir = new File(iconsStoragePath);
        sdIconStorageDir.mkdir();
        try{
            String filePath = sdIconStorageDir.toString() + "pgpPublicKeyRing.pkr";
            FileOutputStream fileOutputStream = new FileOutputStream(filePath);
            BufferedOutputStream out = new BufferedOutputStream(fileOutputStream);
            rsaKr.generatePublicKeyRing().encode(out);
            out.flush();
            out.close();

            String filePath2 = sdIconStorageDir.toString() + "pgpSecretKeyRing.skr";
            FileOutputStream fileOutputStream2 = new FileOutputStream(filePath2);
            BufferedOutputStream out2 = new BufferedOutputStream(fileOutputStream2);
            rsaKr.generateSecretKeyRing().encode(out2);
            out2.close();
        } catch (IOException e){
            e.printStackTrace();
        }
    }

Czy ktoś wie, czego mi tu może brakować?

1

Captain Obvious daje tylko hint : "Can't use an RSA_SIGN key for encryption" - ta wiadomośc oznacza, że kluczem do podpisywania próbujesz szyfrować. Czyli wybierasz zły z keyringa - nie podałes kodu do szyfrowania.

0

Aha czyli muszę przelecieć po wszystkich kluczach i znaleźć ten do szyfrowania?
Ogólnie to przechowuję te klucze w bazie jako string i potem je konwertuję do PGPPublicKey.
Zamieszczam kod poniżej:

 private final static PGPPublicKey getPublicKey(String key) throws IOException {
        InputStream inStream = new ByteArrayInputStream(key.getBytes(Charset.forName("UTF-8")));
        ArmoredInputStream aIn = new ArmoredInputStream(inStream, true);
        BcKeyFingerprintCalculator bck = new BcKeyFingerprintCalculator();
        PGPObjectFactory pgpFact = new PGPObjectFactory(aIn, bck);
        Object o = pgpFact.nextObject();
        PGPPublicKey p = null;
        if ((o instanceof PGPPublicKeyRing)) {
            PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) o;
            p = publicKeyRing.getPublicKey();
        }
        return p;
    }
 public static String encrypt(String msgText, String key) {
        ByteArrayOutputStream encOut = null;
        try {
            byte[] clearData = msgText.getBytes();
            PGPPublicKey encKey = getPublicKey(key);
            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();
        }catch(IOException | PGPException e){
            e.printStackTrace();
        }
        return new String(encOut.toByteArray());
    }
0

Już z tym sobie poradziłem, jarek dzięki za wskazówkę.
Jednak mam teraz problem, żeby przekonwertować zakodowaną wiadomość do stringa.
Musze zamienić tablice "byte" na String, robię to tak:

 return new String(byte,Charset.forName("UTF-8")); 

ale mam krzaki. Jakieś pomysły?

0

A jak kodowane są te bajty które masz? Bo przecież od tego wszystko zależy. Pokaż może te bajty albo skad je wziąłeś ;] Bo UTF-8 to nie iso-8859-1 albo Windows-1250 i wiadomo że dostaniesz krzaki jak sobie tak skonwertujesz.

0

Użyłem innych metod i już ładni wyrzuca mi stringa :)
Wszystko już generalnie działa, na telefonie jak i na linuksie mogę korzystać z kluczy, szyfrować i deszyfrować wiadomości.
Jednak na stronach typu https://www.igolder.com czy innych umożliwiających korzystanie z gpg moje klucze nie działają.
Jak to można wytłumaczyć? Ja mam coś źle?

1

Porównaj format zapisu z tym co działają - dużo walczyłem z** JSON Web Key**.... który wydaje się całkiem dobrze zdefiniowany. (Nie ten algorytm, dodatkowe potrzebne metadane, które niby były opcjonalne, nie ta liczba bitów).

0

Mój klucz zawiera jeszcze subkey, poniżej daję linki do zdekodowanych kluczy:
http://tnijurl.com/kluczonline - ten klucz wygenerowałem online na igolder.com
http://tnijurl.com/kluczzapki/ - ten wygenerowałem w aplikacji.
Na to wychodzi, że musiałbym jakoś inaczej te klucze wyciągać, ale czy jest sens skoro mi w apce działa i na kompie gpg też nie ma z tym problemu?

1 użytkowników online, w tym zalogowanych: 0, gości: 1