Spongy Castle - problem z generowaniem kluczy

Odpowiedz Nowy wątek
2017-01-09 21:26

Rejestracja: 5 lat temu

Ostatnio: 3 lata temu

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ć?

Pozostało 580 znaków

2017-01-10 09:52

Rejestracja: 3 lata temu

Ostatnio: 2 godziny temu

Lokalizacja: U krasnoludów - pod górą

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.


Bardzo lubie Singletony, dlatego robię po kilka instancji każdego.
edytowany 2x, ostatnio: jarekr000000, 2017-01-10 09:54

Pozostało 580 znaków

2017-01-10 10:53

Rejestracja: 5 lat temu

Ostatnio: 3 lata temu

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());
    }

Pozostało 580 znaków

2017-01-10 17:22

Rejestracja: 5 lat temu

Ostatnio: 3 lata temu

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?

Pozostało 580 znaków

2017-01-10 17:26
Moderator

Rejestracja: 16 lat temu

Ostatnio: 6 godzin temu

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.


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...
edytowany 2x, ostatnio: Shalom, 2017-01-10 17:27

Pozostało 580 znaków

2017-01-11 11:18

Rejestracja: 5 lat temu

Ostatnio: 3 lata temu

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?

Pozostało 580 znaków

2017-01-11 11:30

Rejestracja: 3 lata temu

Ostatnio: 2 godziny temu

Lokalizacja: U krasnoludów - pod górą

0

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


Bardzo lubie Singletony, dlatego robię po kilka instancji każdego.

Pozostało 580 znaków

2017-01-11 15:23

Rejestracja: 5 lat temu

Ostatnio: 3 lata temu

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?

edytowany 1x, ostatnio: zszpiegz, 2017-01-11 15:24

Pozostało 580 znaków

Odpowiedz

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