日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JAVA解析各种编码密钥对(DER、PEM、openssh公钥)

發布時間:2025/3/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA解析各种编码密钥对(DER、PEM、openssh公钥) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.csdn.net/zhouyuqwert/article/details/8627952

一、DER編碼密鑰對

先說下DER編碼,是因為JCE本身是支持DER編碼密鑰對的解析的,可以參見PKCS8EncodedKeySpec和X509EncodedKeySpec.

DER編碼是ASN.1編碼規則中的一個子集,具體格式如何編排沒有去了解,但最終呈現肯定的是一堆有規律的二進制組合而成。

PKCS#8定義了私鑰信息語法和加密私鑰語法,而X509定義證書規范,通常都會用DER和PEM進行編碼存儲,而在JAVA中則使用的

DER。


接下來看看如果通過DER編碼的密鑰對分別獲取JAVA的公私鑰對象。


1.下面一段是生成私鑰對象的,傳入參數是DER編碼的私鑰內容。

[java] view plaincopyprint?
  • @Override??
  • public?PrivateKey?generatePrivateKey(byte[]?key)?throws?NoSuchAlgorithmException,?InvalidKeySpecException?{??
  • ????KeySpec?keySpec?=?new?PKCS8EncodedKeySpec(key);??
  • ????KeyFactory?keyFactory?=?KeyFactory.getInstance("RSA");??
  • ????return?keyFactory.generatePrivate(keySpec);??
  • }??
  • @Overridepublic PrivateKey generatePrivateKey(byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException {KeySpec keySpec = new PKCS8EncodedKeySpec(key);KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePrivate(keySpec);}
    2.下面是生成公鑰對象的,傳入參數是DER編碼公鑰內容,可以看到和生成私鑰的部分非常相似。

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


    二、PEM編碼

    PEM編碼也是密鑰對較常用的編碼方式,openssl則是以PEM編碼為主,相對DER對人可讀性更強,以BASE64編碼呈現,外圍包上類似-----BEGIN RSA PRIVATE KEY-----。


    JCE沒有對PEM直接支持的方式,但是可以通過第三方包例如bouncycastle解析,當然如果想要自己理解pem編碼結構,也可以自己寫代碼解析。


    這里介紹下如何使用bouncycastle進行解析。

    [java] view plaincopyprint?
  • ????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()?{??
  • ??????
  • ????@Override??
  • ????public?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));??
  • 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));

    看下這個輸出結果

    [plain] view plaincopyprint?
  • RSA?Public?Key??
  • ????????????modulus:?c8f3e2d2e7fffe049127a115cab648fa9f55a7712d40868dccbddef9ebf030480a31f060e6c1ace2c53660e467cd173870367223dccea00ef2bdf6795757eb34fe1e8cfb63a0d333eefc9739029512df68108dd4b8054a12bdb206abd2ee7a727faa79604680c1337473ecd3d9a1a10b6cbc3af7862a74619ea7fe3a5bb2b89dded41dc5e4e4d5fcad169b85a599487929de1788e1e9a8d4efae4fda811d1e4d975b50d0d61b5887402ca975ec5e1d3ff193522b84746fe35ab00d073fed466786d9303f19c642c02cb1ad3a1ec6f0b7234e492e79500ee0bb1c1f07c23ae70af9b75aa35a6c75573d302cbf8f034341932dc371689b9f952388328c5277c117??
  • ????public?exponent:?10001??
  • ??
  • RSA?Private?CRT?Key??
  • ????????????modulus:?c8f3e2d2e7fffe049127a115cab648fa9f55a7712d40868dccbddef9ebf030480a31f060e6c1ace2c53660e467cd173870367223dccea00ef2bdf6795757eb34fe1e8cfb63a0d333eefc9739029512df68108dd4b8054a12bdb206abd2ee7a727faa79604680c1337473ecd3d9a1a10b6cbc3af7862a74619ea7fe3a5bb2b89dded41dc5e4e4d5fcad169b85a599487929de1788e1e9a8d4efae4fda811d1e4d975b50d0d61b5887402ca975ec5e1d3ff193522b84746fe35ab00d073fed466786d9303f19c642c02cb1ad3a1ec6f0b7234e492e79500ee0bb1c1f07c23ae70af9b75aa35a6c75573d302cbf8f034341932dc371689b9f952388328c5277c117??
  • ????public?exponent:?10001??
  • ???xxx??
  • ??
  • Sun?RSA?public?key,?2048?bits??
  • ??modulus:?25367925677263221630752072905429434117596189021449325931333193529363239091429133073657699480437320802724298965580526553453499379398405915207286949216370963889754756788008021698178495726807109888833039800230667805051637457878962812581009778614579379073430749907762728841603230968432191178635884450213875555645164935313884823663096624318071901833679005494934145072511042211644746801428698070096755012497436134537077746175344235590315572214836519284172251946833712681076781034466422251569387242330311670205489884189790153154281087401570994337126054046621401176808489895271448688335849540690562754961439975230588159770903??
  • ??public?exponent:?65537??
  • Sun?RSA?private?CRT?key,?2048?bits??
  • ??modulus:??????????25367925677263221630752072905429434117596189021449325931333193529363239091429133073657699480437320802724298965580526553453499379398405915207286949216370963889754756788008021698178495726807109888833039800230667805051637457878962812581009778614579379073430749907762728841603230968432191178635884450213875555645164935313884823663096624318071901833679005494934145072511042211644746801428698070096755012497436134537077746175344235590315572214836519284172251946833712681076781034466422251569387242330311670205489884189790153154281087401570994337126054046621401176808489895271448688335849540690562754961439975230588159770903??
  • ??public?exponent:??65537??
  • ??xxx??
  • RSA Public Keymodulus: c8f3e2d2e7fffe049127a115cab648fa9f55a7712d40868dccbddef9ebf030480a31f060e6c1ace2c53660e467cd173870367223dccea00ef2bdf6795757eb34fe1e8cfb63a0d333eefc9739029512df68108dd4b8054a12bdb206abd2ee7a727faa79604680c1337473ecd3d9a1a10b6cbc3af7862a74619ea7fe3a5bb2b89dded41dc5e4e4d5fcad169b85a599487929de1788e1e9a8d4efae4fda811d1e4d975b50d0d61b5887402ca975ec5e1d3ff193522b84746fe35ab00d073fed466786d9303f19c642c02cb1ad3a1ec6f0b7234e492e79500ee0bb1c1f07c23ae70af9b75aa35a6c75573d302cbf8f034341932dc371689b9f952388328c5277c117public exponent: 10001RSA Private CRT Keymodulus: c8f3e2d2e7fffe049127a115cab648fa9f55a7712d40868dccbddef9ebf030480a31f060e6c1ace2c53660e467cd173870367223dccea00ef2bdf6795757eb34fe1e8cfb63a0d333eefc9739029512df68108dd4b8054a12bdb206abd2ee7a727faa79604680c1337473ecd3d9a1a10b6cbc3af7862a74619ea7fe3a5bb2b89dded41dc5e4e4d5fcad169b85a599487929de1788e1e9a8d4efae4fda811d1e4d975b50d0d61b5887402ca975ec5e1d3ff193522b84746fe35ab00d073fed466786d9303f19c642c02cb1ad3a1ec6f0b7234e492e79500ee0bb1c1f07c23ae70af9b75aa35a6c75573d302cbf8f034341932dc371689b9f952388328c5277c117public exponent: 10001xxxSun RSA public key, 2048 bitsmodulus: 25367925677263221630752072905429434117596189021449325931333193529363239091429133073657699480437320802724298965580526553453499379398405915207286949216370963889754756788008021698178495726807109888833039800230667805051637457878962812581009778614579379073430749907762728841603230968432191178635884450213875555645164935313884823663096624318071901833679005494934145072511042211644746801428698070096755012497436134537077746175344235590315572214836519284172251946833712681076781034466422251569387242330311670205489884189790153154281087401570994337126054046621401176808489895271448688335849540690562754961439975230588159770903public exponent: 65537 Sun RSA private CRT key, 2048 bitsmodulus: 25367925677263221630752072905429434117596189021449325931333193529363239091429133073657699480437320802724298965580526553453499379398405915207286949216370963889754756788008021698178495726807109888833039800230667805051637457878962812581009778614579379073430749907762728841603230968432191178635884450213875555645164935313884823663096624318071901833679005494934145072511042211644746801428698070096755012497436134537077746175344235590315572214836519284172251946833712681076781034466422251569387242330311670205489884189790153154281087401570994337126054046621401176808489895271448688335849540690562754961439975230588159770903public exponent: 65537xxx 中間內容太多,略去了一部分,看下重點的public exponent部分,發現不同,但其實是一個是10進制輸出,一個是16進制輸出,所以在這里提個醒,這里生成過程沒有錯的。


    三、openssh公鑰

    很多SSH公鑰習慣使用openssh格式的,下面介紹下openssh格式的公鑰如何解析,目前好像是沒有官方庫或者第三方庫提供支持的。

    openssh公鑰呈現形式如

    [plain] view plaincopyprint?
  • ssh-rsa?AAAAB3NzaC1yc2EAAAADAQABAAAAgQCW6qYq6m8gVOWLyTB1JGl1aLrJDOCIfErXWNUsNeUXg4UdAtSbkiA+Ta9Nx6oMR4w+OkPbxyivnzkZt1YpmDxrm1z99z81/VyVw+lue+3neRjTgfGMascG+46b7DpEKLXlfS2hwOA+4ooRIeR+LbQZVovy5SP6ZTngskiqcySYqQ==?RSA-1024??
  • ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCW6qYq6m8gVOWLyTB1JGl1aLrJDOCIfErXWNUsNeUXg4UdAtSbkiA+Ta9Nx6oMR4w+OkPbxyivnzkZt1YpmDxrm1z99z81/VyVw+lue+3neRjTgfGMascG+46b7DpEKLXlfS2hwOA+4ooRIeR+LbQZVovy5SP6ZTngskiqcySYqQ== RSA-1024

    以ssh-rsa打頭,描述“RSA-1024”結尾的形式,中間是Base64編碼。

    這里過濾掉除了Base64外的其他部分,解碼Base64得到公鑰二進制內容。

    這里二進制編碼格式如下:

    前11字節固定

    0 0 0 7 ?'s' 's' 'h'?'-'?‘r' 's' 'a'?

    緊接著4個字節為一個int值,表示public exponent所占字節長度

    可通過移位符及相加或者BigInteger方式實現轉換。

    [java] view plaincopyprint?
  • ????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; ??
  • ????}??
  • 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;}
    得到長度后,再從后一字節開始讀取該長度字節作為public exponent的值,構造相應BigInteger。


    再緊接著4個字節也是一個int值,表示modulus所占字節長度,同理轉換得到長度。

    再根據長度讀取字節數組得到modulus值即可。


    相應代碼如下

    [java] view plaincopyprint?
  • 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);??
  • }??
  • 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);}

    四、其他編碼

    后續有機會再研究其他編碼方式如何解析,不過可能bouncycastle已經提供了許多編碼的解析,可以直接使用,具體沒看,有興趣的可以研究下。
    下面有個網站介紹各種編碼的,還有利用openssl進行各種轉換的 http://myonlineusb.wordpress.com/2011/06/19/what-are-the-differences-between-pem-der-p7bpkcs7-pfxpkcs12-certificates/ 更多 0

    總結

    以上是生活随笔為你收集整理的JAVA解析各种编码密钥对(DER、PEM、openssh公钥)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。