Java parses various encoding key pairs (DER, PEM, OpenSSH public keys)

Source: Internet
Author: User
Tags begin rsa private key modulus
1. Der-encoded key pair

Let's talk about DER encoding because JCE supports DER encoding key pair parsing. For details, see pkcs8encodedkeyspec and x509encodedkeyspec.

DER encoding is a subset of the ASN.1 encoding rules. We do not know how to orchestrate the specific formats, but it is definitely a combination of regular binary codes.

PKCS #8 defines the private key information syntax and the encryption Private Key syntax, while X509 defines the certificate specification, usually using DER and PEM for encoding storage, while Java uses

Der.

Next, let's take a look at how to obtain the Java public/private key objects through der-encoded key pairs.

1. The following section generates the private key object. The input parameter is the DER-encoded private key content.

@Overridepublic PrivateKey generatePrivateKey(byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException {KeySpec keySpec = new PKCS8EncodedKeySpec(key);KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePrivate(keySpec);}

2. The following is a public key object generated. The input parameter is der-encoded public key content. It can be seen that it is very similar to the part that generates the private key.

public PublicKey geneneratePublicKey(byte[] key) throws InvalidKeySpecException, NoSuchAlgorithmException{KeySpec keySpec = new X509EncodedKeySpec(key);KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePublic(keySpec);}

Ii. pem Encoding

PEM encoding is also a common encoding method for key pairs. OpenSSL is mainly based on PEM encoding, which is more readable to people than der and presented in base64 encoding. It is similar to ----- begin RSA private key ----- on the peripheral package -----.

JCE does not directly support PEM, but it can be parsed by a third-party package such as bouncycastle. Of course, if you want to understand the PEM encoding structure, you can also write your own code for parsing.

This section describes how to use bouncycastle for parsing.

    FileInputStream fis = new FileInputStream("id_rsa");    byte[] key = PrivateKeyUtils.readStreamToBytes(fis);Security.addProvider(new BouncyCastleProvider());ByteArrayInputStream bais = new ByteArrayInputStream(key);PEMReader reader = new PEMReader(new InputStreamReader(bais), new PasswordFinder() {@Overridepublic char[] getPassword() {return "".toCharArray();}});KeyPair keyPair = (KeyPair) reader.readObject();reader.close();PublicKey pubk = keyPair.getPublic();System.out.println(pubk);PrivateKey prik = keyPair.getPrivate();System.out.println(prik);KeySpec keySpec = new X509EncodedKeySpec(pubk.getEncoded());KeyFactory keyFactory = KeyFactory.getInstance("RSA");System.out.println(keyFactory.generatePublic(keySpec));KeySpec keySpec2 = new PKCS8EncodedKeySpec(prik.getEncoded());System.out.println(keyFactory.generatePrivate(keySpec2));

 

Check the output.

RSA Public Key            modulus: c8f3e2d2e7fffe049127a115cab648fa9f55a7712d40868dccbddef9ebf030480a31f060e6c1ace2c53660e467cd173870367223dccea00ef2bdf6795757eb34fe1e8cfb63a0d333eefc9739029512df68108dd4b8054a12bdb206abd2ee7a727faa79604680c1337473ecd3d9a1a10b6cbc3af7862a74619ea7fe3a5bb2b89dded41dc5e4e4d5fcad169b85a599487929de1788e1e9a8d4efae4fda811d1e4d975b50d0d61b5887402ca975ec5e1d3ff193522b84746fe35ab00d073fed466786d9303f19c642c02cb1ad3a1ec6f0b7234e492e79500ee0bb1c1f07c23ae70af9b75aa35a6c75573d302cbf8f034341932dc371689b9f952388328c5277c117    public exponent: 10001RSA Private CRT Key            modulus: c8f3e2d2e7fffe049127a115cab648fa9f55a7712d40868dccbddef9ebf030480a31f060e6c1ace2c53660e467cd173870367223dccea00ef2bdf6795757eb34fe1e8cfb63a0d333eefc9739029512df68108dd4b8054a12bdb206abd2ee7a727faa79604680c1337473ecd3d9a1a10b6cbc3af7862a74619ea7fe3a5bb2b89dded41dc5e4e4d5fcad169b85a599487929de1788e1e9a8d4efae4fda811d1e4d975b50d0d61b5887402ca975ec5e1d3ff193522b84746fe35ab00d073fed466786d9303f19c642c02cb1ad3a1ec6f0b7234e492e79500ee0bb1c1f07c23ae70af9b75aa35a6c75573d302cbf8f034341932dc371689b9f952388328c5277c117    public exponent: 10001   xxxSun RSA public key, 2048 bits  modulus: 25367925677263221630752072905429434117596189021449325931333193529363239091429133073657699480437320802724298965580526553453499379398405915207286949216370963889754756788008021698178495726807109888833039800230667805051637457878962812581009778614579379073430749907762728841603230968432191178635884450213875555645164935313884823663096624318071901833679005494934145072511042211644746801428698070096755012497436134537077746175344235590315572214836519284172251946833712681076781034466422251569387242330311670205489884189790153154281087401570994337126054046621401176808489895271448688335849540690562754961439975230588159770903  public exponent: 65537Sun RSA private CRT key, 2048 bits  modulus:          25367925677263221630752072905429434117596189021449325931333193529363239091429133073657699480437320802724298965580526553453499379398405915207286949216370963889754756788008021698178495726807109888833039800230667805051637457878962812581009778614579379073430749907762728841603230968432191178635884450213875555645164935313884823663096624318071901833679005494934145072511042211644746801428698070096755012497436134537077746175344235590315572214836519284172251946833712681076781034466422251569387242330311670205489884189790153154281087401570994337126054046621401176808489895271448688335849540690562754961439975230588159770903  public exponent:  65537  xxx

There is too much content in the middle. I skipped a part and looked at the public exponent part. I found it was different, but it was actually a 10-digit output and a 16-digit output, so let's make a note here. There is no error in the generation process here.

Iii. OpenSSH Public Key

Many SSH public keys are used to the OpenSSH format. The following describes how to parse the public keys in OpenSSH format. Currently, there seems to be no official library or a third-party library.

The format of the OpenSSH Public Key is as follows:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCW6qYq6m8gVOWLyTB1JGl1aLrJDOCIfErXWNUsNeUXg4UdAtSbkiA+Ta9Nx6oMR4w+OkPbxyivnzkZt1YpmDxrm1z99z81/VyVw+lue+3neRjTgfGMascG+46b7DpEKLXlfS2hwOA+4ooRIeR+LbQZVovy5SP6ZTngskiqcySYqQ== RSA-1024

Headers with ssh-RSA to describe the form of the end of the RSA-1024, with base64 encoding in the middle.

Here, we can filter out other parts except base64 and decode base64 to obtain the binary content of the public key.

The binary encoding format is as follows:

The first 11 bytes are fixed

0 0 0 7's 'H'-'R''s 'A'

The next four bytes are an int value, indicating the length of the public exponent.

The conversion can be realized by means of Shift Operators, addition, or biginteger.

public static int decodeUInt32(byte[] key, int start_index){byte[] test = Arrays.copyOfRange(key, start_index, start_index + 4);return new BigInteger(test).intValue();//int int_24 = (key[start_index++] << 24) & 0xff;//int int_16 = (key[start_index++] << 16) & 0xff;//int int_8 = (key[start_index++] << 8) & 0xff;//int int_0 = key[start_index++] & 0xff;//return int_24 + int_16 + int_8 + int_0;}

After obtaining the length, read the length from the last byte as the value of public exponent and construct the corresponding biginteger.

The next four bytes are also an int value, indicating that modulus occupies the length of the byte. Similarly, the length is obtained through conversion.

Then, read the byte array based on the length to obtain the modulus value.

The Code is as follows:

public static RSAPublicKey decodePublicKey(byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException{byte[] sshrsa = new byte[] { 0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's','a' };int start_index = sshrsa.length;/* Decode the public exponent */int len = decodeUInt32(key, start_index);start_index += 4;byte[] pe_b = new byte[len];for(int i= 0 ; i < len; i++){pe_b[i] = key[start_index++];}BigInteger pe = new BigInteger(pe_b);/* Decode the modulus */len = decodeUInt32(key, start_index);start_index += 4;byte[] md_b = new byte[len];for(int i = 0 ; i < len; i++){md_b[i] = key[start_index++];}BigInteger md = new BigInteger(md_b);KeyFactory keyFactory = KeyFactory.getInstance("RSA");KeySpec ks = new RSAPublicKeySpec(md, pe);return (RSAPublicKey) keyFactory.generatePublic(ks);}

4. Other encodings will have the opportunity to study how to parse Other encoding methods in the future. However, bouncycastle may have provided many encoding resolutions that can be used directly. If you are interested, you can study them. The following is a website to introduce various encoding, as well as the use of OpenSSL for various conversion http://myonlineusb.wordpress.com/2011/06/19/what-are-the-differences-between-pem-der-p7bpkcs7-pfxpkcs12-certificates/
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.