Creating RSA Public Key From String

后端 未结 2 1746
深忆病人
深忆病人 2020-12-03 14:10

I\'ve generated this test public key using 1024 RSA and then encoded it to DER and Base64 in another coding platform. I copied the key into a string in Android/Eclipse and I

相关标签:
2条回答
  • 2020-12-03 15:02

    For those who dont want to use Bouncy Castle

    public class RSAKeySeperation {
    
    
    public static void main(String[] args) throws InvalidKeySpecException, NoSuchAlgorithmException {
        String publicKeyB64 = "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBV8xakN/wOsB6qHpyMigk/5PrSxxd6tKTJsyMIq5f9npzZue0mI4H2o8toYImtRk6VHhcldo0t7UwsQXmFMk7D"
                + "i3C53Xwfk7yEFSkXGpdtp/7fbqNnjVoJl/EPcgoDsTPrHYF/HgtmbhzuYvYeY1zpV0d2uYpFxAuqkE9FreuuH0iI8xODFe5NzRevXH116elwdCGINeAecHKgiWe"
                + "bGpRPml0lagrfi0qoQvNScmi/WIN2nFcI3sQFCq3HNYDBKDhO0AEKPB2FjvoEheJJwTs5URCYsJglYyxEUon3w6KuhVa+hzYJUAgNTCsrAhQCUlX4+5LOGlwI5gonm1DYvJJZAgMBAAEB";
        byte[] decoded = Base64.getDecoder().decode(publicKeyB64);
        X509EncodedKeySpec spec =
                new X509EncodedKeySpec(decoded);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        RSAPublicKey generatePublic = (RSAPublicKey) kf.generatePublic(spec);
        BigInteger modulus = generatePublic.getModulus();
        System.out.println(modulus);
        BigInteger exponent = generatePublic.getPublicExponent();
        System.out.println(exponent);
    }
    
    }
    
    0 讨论(0)
  • 2020-12-03 15:04

    The key you have is in PKCS#1 format instead of SubjectPublicKeyInfo structure that Java accepts. PKCS#1 is the encoding of the RSA parameters only and lacks things such as an algorithm identifier. SubjectPublicKeyInfo uses PKCS#1 internally - for RSA public keys anyway.

    As the PKCS#1 public key is at the end of the SubjectPublicKeyInfo structure it is possible to simply prefix the bytes so that they become an RSA SubjectPublicKeyInfo. That solution is easier to perform without additional libraries such as Bouncy Castle. So if you need to go without an external library then you may have a look at my answer here.


    Alternatively a simple BER decoder could be written to decode the structure into the two BigInteger values. The structure itself is not that complicated but the BER/DER length encoding takes some getting used to.

    However, you can also use Bouncy Castle (lightweight API) to solve your issues:

    String publicKeyB64 = "MIGHAoGBAOX+TFdFVIKYyCVxWlnbGYbmgkkmHmEv2qStZzAFt6NVqKPLK989Ow0RcqcDTZaZBfO5"
            + "5JSVHNIKoqULELruACfqtGoATfgwBp4Owfww8M891gKNSlI/M0yzDQHns5CKwPE01jD6qGZ8/2IZ"
            + "OjLJNH6qC9At8iMCbPe9GeXIPFWRAgER";
    // ok, you may need to use the Base64 decoder of bouncy or Android instead
    byte[] decoded = Base64.getDecoder().decode(publicKeyB64);
    org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(decoded);
    BigInteger modulus = pkcs1PublicKey.getModulus();
    BigInteger publicExponent = pkcs1PublicKey.getPublicExponent();
    RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExponent);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PublicKey generatedPublic = kf.generatePublic(keySpec);
    System.out.printf("Modulus: %X%n", modulus);
    System.out.printf("Public exponent: %d ... 17? Why?%n", publicExponent); // 17? OK.
    System.out.printf("See, Java class result: %s, is RSAPublicKey: %b%n", generatedPublic.getClass().getName(), generatedPublic instanceof RSAPublicKey);
    

    As you can see it actually only requires a single class as interface, although that is of course backed up with the entire ASN.1/BER decoder functionality within Bouncy Castle.


    Note that it may be required to change the Base 64 decoder to the Android specific one (android.util.Base64). This code was tested on an equivalent Java runtime.

    0 讨论(0)
提交回复
热议问题