Java의 OpenSSL에서 생성 한 RSA 공개 및 개인 키를 사용한 데이터 암호화 및 암호 해독
RSA는 무엇입니까? RSA 공개 키 암호화 알고리즘은 1977 년 Ron Rivest, Adi Shamirh 및 Len Adleman (Massachusetts Institute of Technology)에 의해 개발되었습니다. RSA 이름은 세 가지를 개발하는 이름에서 비롯됩니다. RSA는 현재 가장 영향력있는 공개 키 암호화 알고리즘입니다. 지금까지 알려진 모든 암호화 공격에 저항 할 수 있으며 ISO에 의해 공개 키 데이터 암호화 표준으로 권장되었습니다. 현재이 암호화 방법은 온라인 뱅킹, 디지털 서명 및 기타 경우에 널리 사용됩니다. RSA 알고리즘은 매우 간단한 숫자 이론 사실을 기반으로합니다. 두 개의 큰 소수를 곱하기는 매우 쉽지만 그 당시 제품을 고려하는 것은 매우 어려웠으므로 제품을 암호화 키로 공개 할 수 있습니다.
OpenSSL이란 무엇인가 : 수많은 암호화 알고리즘, 공개 키 인프라 표준 및 SSL 프로토콜 및 이러한 흥미로운 기능은 이러한 알고리즘과 표준을 모두 구현할 수있는 아이디어를 제공 할 것입니다. 그렇다면, 당신의 감탄을 표현하는 동안, 나는 여전히 도울 수는 없지만 당신에게 상기시켜줍니다. 이것은 어려운 과정입니다. 이 작업은 더 이상 몇 가지 암호화 논문 및 프로토콜 문서를 읽는 것만 큼 간단하지 않고 이러한 모든 알고리즘, 표준 및 프로토콜 문서의 모든 세부 사항을 이해하고 이러한 정의 및 프로세스를 하나씩 친숙 할 수 있습니다. 우리는이 재미 있고 끔찍한 일을하는 데 얼마나 많은 시간이 필요한지 모르지만, 1 년 또는 두 번의 문제는 아닙니다. OpenSSL은 1995 년부터 Eric A. Young과 Tim J. Hudson의 두 위대한 남자가 작성한 많은 보안 알고리즘을 결합한 알고리즘 컬렉션입니다. 명령 또는 개발 라이브러리를 통해 표준 공개 알고리즘 응용 프로그램을 쉽게 구현할 수 있습니다.
내 가상의 응용 프로그램 배경 중 하나 :
모바일 인터넷의 인기로 인해 모바일 장치 용 응용 프로그램이 떠오르고 있습니다. 이러한 응용 프로그램에는 종종 사용자 등록 및 비밀번호 확인 기능이 동반됩니다. "네트워크 전송"및 "애플리케이션 로그 액세스"에는 보안에 숨겨진 위험이 있습니다. 암호는 사용자에게 민감한 데이터이며 개발자는 응용 프로그램을 시작하기 전에 보안 예방 조치를 취해야합니다. 부적절한 취급으로 인해 비즈니스 경쟁자의 악의적 인 공격 및 타사 파트너의 소송과 같은 문제가 발생할 수 있습니다.
RSA 알고리즘에는 많은 이점이 있지만 인터넷에이를 작동하는 방법을 설명하기위한 완전한 예는 없습니다. 아래에 소개하겠습니다.
1. OpensSL을 사용하여 개인 및 공개 키를 생성하십시오
Linux 시스템을 사용하고 있으며 OpenSSL 패키지가 설치되어 있습니다. OpenSSL이 컴퓨터에 설치되어 있는지 확인하십시오. 명령을 실행할 때 다음 정보가 나타납니다.
[root@chaijunkun ~]# OpenSSL 버전 -a OpenSSL 1.0.0 -ofips 29 2010 년 3 월 29 일 빌딩 : 수요일 1 월 25 일 02:17:15 GMT 2012 플랫폼 : Linux -X86_64 옵션 : BN (64,64) MD2 (INT) RC4 (16X, int) DES (Idx, CISC, 16, int) BLOPLER : GC COMPIC : gcc -gcc -gcc -int) compiler : -dopenssl_pic -dzlib -dopenssl_threads -d_reentrant -ddso_dlfcn -dhave_dlfcn_h -dkrb5_mit -m64 -dtermio -wall -o2 -g -pipe -wall -Wall -Wall -Wall -Wall -Wall -Wall -Wall -WARTORCE = 2 -FETOURCES = 2 -FETERCUTES = -param = ssp -buffer -size = 4 -m64 -mtune = generic -wa, -noexecstack -dmd32_reg_t = int -dopenssl_ia32_sse2 -dopenssl_bn_sasm_mont -dsha1_asm -dsha256_asm -dsha512_asm-dmd5_asm -dasmd5_asm _asm -dasmd 512_asm. -dwhirlpool_asm openssldir : "/etc/pki/tls"엔진 : Aesni Dynamic
먼저 개인 키 생성 :
[root@chaijunkun ~]# OpenSSL GERSA -OUT RSA_PRIVATE_KEY.PEM 1024 RSA 개인 키 생성, 1024 비트 긴 모듈러스 .................. ++++++ .. ++++++ e는 65537 (0x10001)입니다.
이 명령은 OpenSSL이 개인 키를 무작위로 생성 할 수 있으며 암호화 길이는 1024 비트입니다. 암호화 된 길이는 허용 된 최대 "암호화 된 정보"길이, 즉 일반 텍스트의 길이 한계의 이론적 한계를 나타냅니다. 이 매개 변수가 증가함에 따라 (예 : 2048), 허용 된 일반 텍스트 길이도 증가하지만 컴퓨팅 복잡성이 급격히 증가합니다. 권장 길이는 1024 비트 (128 바이트)입니다.
개인 키의 내용을 살펴 보겠습니다.
[root@chaijunkun ~]# cat rsa_private_key.pem ----- 시작 rsa private key ----- miicwwibaakbgqchdzcjw/rwgfwnxunbkp7/4e8w/umxx2jk6qeen69t6n2r1i/l mcydt1xr/t2ahgoixnq5v8w4icaaaenawi7ajarhtvx1uoh/2u378fsceesegesegesegeg8xdq ll0gcfb1/tjki2aitvszxotrs8kyggu78f7vmdngxilk3gdnzh+uoe qywida quida aogaaekk76cssp7k90mwywp18ghlzru+quffvpv67cglg1owfbntfyqspvstfm u2lwn5hd/icv+egaj4folxdm43kt4wyznoabszckkxs6urciu8nqafnuy4xveofx phu2te7vi4ldkw9df1fya+dscslnadaun3ohb5jqgl+ls5ecqdufuxxn3uqgykk znrkj0j6py27hrfromehgxbjnapcq71szjqam77r3wilkfh935oqc4jqcrb4 IHYSLL9LAKEAWGH4JXXXEIAUFMSGJOI3QPJQGVUMKX0W96MCPCWV3FSEW7W1/MSI SUTKJP5BBVVJFVFWWWWWWWWWWWWWWWFWWMAHYLJDP7W+NEBWKBWJAYBZ/있었다 egplwsji/mkhrb484xz2vyiuiciwywnmfxpa3ydgqwskqdgy3rrl9lv8/qjacjli ifigur ++ njxa8c4xy0czsobj76k710wde1mpgr5wgqf1t+p+bcpjyvyv /ybxbd16qvixjvnt6qjabli6zx9gyrwnu6akpdahd8qjwonnnfnlqhue4wepevkm cysg+ibs2ggsxntrzlwjlwjlfx7vhmpqnttc8ynmx1kfw == -------------------------
내용은 모두 표준 ASCII 문자이며, 시작 및 끝 라인에 명백한 마크가 있으며 실제 개인 키 데이터는 중간에 불규칙한 문자입니다.
2015 년 3 월 24 일 보충 : 키 파일은 결국 Base64 인코딩을 통해 데이터를 저장합니다. 위의 키 파일 컨텐츠의 각 줄의 길이는 매우 규칙적임을 알 수 있습니다. 이는 RFC2045의 조항에 기인합니다. 인코딩 된 출력 스트림은 각각 76 자 이하의 라인으로 표시되어야합니다. 즉, Base64로 인코딩 된 데이터는 라인 당 76자를 초과하지 않으며 초대형 데이터의 경우 행으로 나누어야합니다.
다음으로 개인 키를 기반으로 공개 키를 생성하십시오.
[root@chaijunkun ~]# OpenSSL rsa -in rsa_private_key.pem -out rsa_public_key.pem -pemout 쓰기 RSA 키
공개 키의 내용을 살펴 보겠습니다.
[root@chaijunkun ~]# cat rsa_public_ley.pem ----- 시작 공개 키 ----- MIGFMA0GCSQGSIB3DQEBAQUAA4GNADCBIQKBGQCHDZCJW/RWGFWNXUNBKP7/4E8W /umxx2jk6qeen69t6n2r1i/lmcydt1xr/t2ahgoixnq5v8w4icaaaenawi7ajarht vx1uoh/2u378fsceeseg8xdqll0gcfb1/tjki2aitvszxotrs8kygggu78f7vmdng xilk3gdhnzh+uoeqywidaqab ---- 엔드 퍼블릭 키 ----
현재 개인 키는 직접 사용할 수 없으므로 PKCS#8 인코딩이 필요합니다.
[root@chaijunkun ~]# OpenSSL pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt
명령은 입력 개인 키 파일이 rsa_private_key.pem이고 출력 개인 키 파일은 pkcs8_rsa_private_key.pem이며 2 차 암호화가 사용되지 않음 (-nocrypt)을 나타냅니다.
인코딩 된 개인 키 파일이 이전 개인 키 파일과 다른지 여부를 살펴 보겠습니다.
[root@chaijunkun ~]# cat pkcs8_rsa_private_key.pem
----- 시작 개인 키 ----- MIICDQIBADANBGKQHKHKIG9W0BAQEFAASCAL8WGGJBACEEAOOGBAKEPNYPD+TAAXCFG 6DSQNV/H7ZD9SZFHAOTQOQSFR23ZHWL8UZZINPXGV9PYACY6JC1DLXXBP4 1RCLTOLPGG1XHW44F/ZTFVX+XWQRIQBXCOQWXQYJ8HX9OMOJZQKKKKKKKKKKKKKKKK61GZYRIA ZTVX/TWYM2BCIWTEB2GFOH66GRDLAGMBAEECGYBP4QTVOJKYNUT3SBDJY/XWAETM U768SF9P0GLXRTWYUDWJAVUE0VHBI9WXMWZTAVAFKCP8HXXX4QZQZQPPH84TD0ZJCQ3J DLOEGAFJKIORGZQ5FYK7YDBOU1TLJFV459C8DTZMTU+LGSOTD11/v/jR4NJXIDO MBQ3C4CHMOOYV4UZKJBANR+7FC3E6OZGQTOESQPSPQLJBSDF9E4X4EDFUOECCKJ DVVLOOOOZVTHFAIUP+H3FK4HXRPALINBEHIIDHIUX2UCQDCCHIPHFFDC58YYYCM 6leqkmoa+6ypfrb3oxyklbxcwx7dtbx+ayky5oqmnkeg+mw8xb8wadiul0/tb6cq farvakbhvp94hk0dmdmdinfvhlwyj3xy4pongsa8vcymj+asgtvjzjjjjzxk4gbjjzxk4gbjjjzxxk4g3 2z9ekdfiobbawqp2dldgux2vxz8bakbymuih+kbsv76cnedwlhflqjlkgenvqtvx tb0tuw8avlabaxw34/5si+nub1hmbgytk/t/ifcepxbwlgo+e3pakagwlpnh0zh FAE7OAQKMAD3XCNY6EC180TAE57HZ6KS+SYLKWB4GGZYACXC22VMTYKSXHTUEAMO 1NMLZI2ZFUOX -------------------
이 시점에서 사용 가능한 키 쌍이 생성되었습니다. 개인 키는 pkcs8_rsa_private_key.pem을 사용하고 공개 키는 rsa_public_key.pem을 사용합니다.
2014 년 5 월 20 일에 추가 : 최근에 RSA 암호화의 필요성이 발생했으며 다른 당사자는 첫 번째 단계에서 생성 된 PKCS#8으로 인코딩되지 않은 개인 키 파일 만 사용할 수 있어야했습니다. 나중에 관련 문서를 확인하고 첫 번째 단계에서 생성 된 개인 키 파일이 PKCS#1 형식임을 알게되었습니다. 이 형식은 실제로 Java에서 지원되지만 두 줄의 코드를 더 씁니다.
rsaprivateKeyStructure ASN1PrivKey = 새로운 rSaprivateKeyStructure ((ASN1SECINCENCE) ASN1SECTENCE.FROMBYTERRAY (PrikeyData)); rsaprivatekeyspec rsaprivkeyspec = new rsaprivatekeyspec (asn1privkey.getmodulus (), asn1privkey.getPrivateExponent ()); keyfactory keyfactory = keyfactory.getInstance ( "rsa"); privatekey prikey = keyfactory.generate -private (rsaprivkeyspec);
먼저 PKCS#1의 개인 키 파일을 읽은 다음 (마이너스 부호의 시작 부분에서 주석 내용을 제거한다는 점)를 읽은 다음 Base64를 사용하여 읽기 문자열을 디코딩하여 첫 번째 줄의 매개 변수 인 prikeydata를 가져옵니다. 마지막 줄은 개인 키를 얻습니다. 다음 사용법에는 차이가 없습니다.
참조 : https://community.oracle.com/thread/1529240?start=0&tstart=0
2. Java 코드를 작성하여 테스트하십시오
2012 년 2 월 23 일 : 표준 JDK는 JCE에만 지정되어 있습니다 (JCE (JCE (Java Cryptography Extension)는 암호화, 주요 생성 및 협상 및 메시지 인증 코드 (MAC) 알고리즘을위한 프레임 워크 및 구현을 제공하는 패키지 세트입니다. 암호화, ASYMMETRY, ASYMMETTRY, ASIMMMETRY 및 Strem METSTS 및 스트림 지원을위한 암호화 지원을 제공합니다. 인터페이스는 자체적으로 또는 제 3자가 제공해야합니다. 따라서 우리는 여기에서 바운지 캐스트의 오픈 소스 JCE 구현 패키지를 사용합니다 버전에서는 이전 다운로드 페이지에서 해당 버전을 찾을 수 있습니다.
내가 구현 한 코드를 살펴 보겠습니다.
패키지 net.csdn.blog.chaijunkun; import java.io.bufferedReader; import java.io.ioexception; import java.io.inputstream; import java.io.inputStreamReader; java.security.invalidkeyException 가져 오기; java.security.keyfactory import; java.security.keypair import; java.security.keypairgenerator import; java.security.nosuchalgorithmexception import; java.security.securerandom import; java.security.interfaces.rsaprivatekey 가져 오기; java.security.interfaces.rsapublickey 가져 오기; java.security.spec.invalidkeyspecexception import; java.security.spec.pkcs8encodedkeyspec import; import java.security.spec.x509encodedKeyspec; javax.crypto.badpaddingException import; javax.crypto.cipher 가져 오기; javax.crypto.ilegalblocksizeexception import; javax.crypto.nosuchpaddingException import; import org.bouncycastle.jce.provider.bouncycastleprovider; import sun.misc.base64decoder; 공개 클래스 rsaencrypt {private static final string default_public_key = "migfma0gcsqgsib3dqebaquaa4gnadcbiqkbgqchdzcjw/rwgfwnxunbkp7/4e8w" + "/r" + "/umxx2jk6qeen6qeen69t6n2r1i/lmcydt1xr/t2ahgoixnq5v8w4icaaaenawi7ajarht" + "/r" + "vx1uoh/2u378fsceeseg8xdqll0gcfb1/tjki2aitvszxotrs8kyggu78fgu78fgu78f "/r" + "xilk3gdhnzh + uoeqywidaqab" + "/r"; 비공개 정적 최종 문자열 default_private_key = "miicdqibadanbgkqhkhkig9w0baqefaascal8wggjbageaoogbakepnypd + taaxcfg" + "/r" + "6dsqnv/h7zd9szfhaotqoqsfr23o3zhwl8uzzinpxgvv9pyacy6jc1dlxxbiijpp4" + "/r" + "1RCLTOLPGG1XHW44F/ZTFVX + XWQRIQBXCOQWXQYJ8HX9OMOJZQKK1VLNC61GZYRIA" + "/R" + "ZTVX/TWYM2BCIWTEB2GFOH66GRDLAGMBAAECGYBP4QTVOJKYNUT3SBDJY/XWAETM" + "/R" + "U768SF9P0GLXRTWYUDWJAVUE0VHBI9WXMWZTAVAFKCP8HXX4QZQZQPPH84TD0ZJCQ3J" + "/R" + "dloegafjkiorgzq5fyk7ydbou1tljfv459c8dtzmtu + lgsotd11/v/jr4njxiudo" + "/r" + "MBQ3C4CHMOOYV4UZKJBANR + 7FC3E6OZGQTOESQPSPQLJBSDF9E4X4EDFUOECCKJ" + "/R" + "DVVLOOOAZVTHFAIUP + H3FK4HXRPALINBEHIUX2UCQQDCCHPHFFD4GC58GCM" +"6leqkmoa +6ypfrb3oxyklbxcwx7dtbx +ayky5oqmnkeg +mw8xb8wadiul0/tb6cq" +"/r" + "FARVAKBHVP94HK0DMDINFVHLWYJ3XY4PONGSA8VCYMJ + ASGTVJJZZZZZZZZXK4GIJBJA" + "/R" + "2Z9EKDFIOBBAWQP2DGUX2VXZ8BAKBYMUIH + KBSV76CNDHFLQJLKTVK" + "/r" + "tb0tuw8avlabaxw34/5si + nub1hmbgytk/t/ifcepxpbwlgo + e3pakagwlpnh0zh" + "/r" + "FAE7OAQKMAD3XCNY6EC180TAE57HZ6KS + SYLKWB4GGZYACXC22VMTYKSXHTUEAMO" + "/R" + "1NMLZI2ZFUOX" + "/R"; / *** 개인 키*/ 개인 rsaprivatekey privatekey; / *** 공개 키*/ 개인 rsapublickey publickey; / *** 개인 설정 문자열*/ private static final char [] hex_char = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; / *** 개인 키를 얻으십시오* @return 현재 개인 키 객체*/ public rsaprivatekey getPrivatekey () {return privatekey; } / *** 공개 키 가져 오기* @return 현재 공개 키 객체* / public rsapublickey getPublickey () {return publickey; } / *** 무작위로 생성 된 키 쌍* / public void genkeypair () {kyypairgenerator kyypairgen = null; {kyypairgen = kyypairgenerator.getinstance ( "rsa"); } catch (nosuchalgorithmexception e) {e.printstacktrace (); } kyypairgen.initialize (1024, new securerandom ()); Keypair kyypair = kyypairgen.generatekeypair (); this.privatekey = (rsaprivatekey) kyypair.getPrivate (); this.publickey = (rsapublickey) kyypair.getPublic (); } / *** 파일의 입력 스트림에서 공개 키를 공개 키 입력 스트림에서 @param* @Throws 예외 공개 키* / public void loadPublicKey (inputStream in) 예외 예외 예외 {try {bufferedReader br = new bufferedReader (new inputStreamReader (in)); 문자열 readline = null; StringBuilder sb = new StringBuilder (); while ((readline = br.readline ())! = null) {if (readline.charat (0) == '-') {계속; } else {sb.append (readline); sb.append ( '/r'); }} loadPublicKey (sb.toString ()); } catch (ioException e) {Throw New Exception ( "공개 키 데이터 스트림 읽기 오류"); } catch (nullPointerException e) {Throw New Exception ( "공개 키 입력 스트림이 비어 있습니다"); }} / *** 문자열에서 공개 키를로드* @param publickeyst public key data string* @throws 예외 공개 키* / public void loadpublickey (String publicKeyst) 예외 예외 {try {base64decoder base64decoder = new Base64decoder (); 바이트 [] buffer = base64decoder.decodebuffer (publickeystr); keyfactory keyfactory = keyfactory.getInstance ( "rsa"); X509ENCODEDKEYSPEC KEYSPEC = NEW X509ENCODEDKEYSPEC (버퍼); this.publickey = (rsapublickey) keyfactory.generatepublic (keyspec); } catch (nosuchalgorithmexception e) {새로운 예외를 던집니다 ( "아무것도 알고리즘"); } catch (invalidkeyspecexception e) {새로운 예외 ( "공개 키 불법"); } catch (ioException e) {Throw New Exception ( "공개 키 데이터 컨텐츠 읽기 오류"); } catch (nullPointerException e) {Throw New Exception ( "공개 키 데이터가 비어 있습니다"); }} / *** 파일에서 개인 키를로드* @param keyfilename 개인 키 파일 이름* @return 성공 여부* @Throws Exception* / public void loadPrivateKey (inputStream in) 예외 {try {bufferedReader br = new bufferedReader (new inputStreamReader (in)); 문자열 readline = null; StringBuilder sb = new StringBuilder (); while ((readline = br.readline ())! = null) {if (readline.charat (0) == '-') {계속; } else {sb.append (readline); sb.append ( '/r'); }} loadPrivateKey (sb.toString ()); } catch (ioException e) {Throw New Exception ( "개인 키 데이터 읽기 오류"); } catch (nullPointerException e) {Throw New Exception ( "개인 키 입력 스트림이 비어 있습니다"); }} public void loadPrivateKey (String privateKeyStr)는 예외를 던지려면 {try {base64decoder base64decoder = new Base64decoder (); 바이트 [] buffer = base64decoder.decodebuffer (privatekeystr); PKCS8ENCODEDKEYSPEC KEYSPEC = NEW PKCS8ENCODEDKEYSPEC (버퍼); keyfactory keyfactory = keyfactory.getInstance ( "rsa"); this.privatekey = (rsaprivatekey) keyfactory.generate -private (keyspec); } catch (nosuchalgorithmexception e) {새로운 예외 ( "이 알고리즘은 없음"); } catch (invalidkeyspecexception e) {새로운 예외 ( "개인 키 불법"); } catch (ioException e) {Throw New Exception ( "개인 키 데이터 컨텐츠 읽기 오류"); } catch (nullPointerException e) {Throw New Exception ( "개인 키 데이터가 비어 있습니다"); }} / *** 암호화 프로세스* @param publickey public key* @param plaintextdata plaintext data* @Throws 암호화 프로세스 중 예외 정보 예외 정보* / public byte [] 암호화 (rsapublickey publickey, byte [] PlainTextData) 예외 {publickey = emply experction ( "accryption is newption"); } cipher cipher = null; try {cipher = cipher.getinstance ( "rsa", new bouncycastleprovider ()); cipher.init (cipher.encrypt_mode, publickey); 바이트 [] output = cipher.dofinal (PlainTextData); 리턴 출력; } catch (nosuchalgorithmexception e) {새로운 예외 ( "Nothis 암호화 알고리즘"); } catch (nosuchPaddingException e) {e.printstacktrace (); 널 리턴; } catch (invalidkeyException e) {새 예외 던지기 ( "암호화 공개 키는 불법입니다. 확인하십시오"); } catch (불법 블록 시지 렉스 션 e) {새 예외를 던지십시오 ( "plackText 길이는 불법"); } catch (badpaddingException e) {Throw New Exception ( "PlackText 데이터가 손상되었습니다"); }} / *** 암호 해독 프로세스* @param privatekey private key* @param cipherdata ciphertext data* @Throws exception excection inforection* / public byte [] deScrypt [] decrypt (rsaprivatekey, byte [] cipherdata [] cipherdata [] cipherdata) {private key excep { "null null) {null null). 세트"); } cipher cipher = null; try {cipher = cipher.getinstance ( "rsa", new bouncycastleprovider ()); cipher.init (cipher.decrypt_mode, privatekey); 바이트 [] 출력 = cipher.dofinal (cipherdata); 리턴 출력; } catch (nosuchalgorithmexception e) {새로운 예외 ( "없음 암호 해독 알고리즘"); } catch (nosuchPaddingException e) {e.printstacktrace (); 널 리턴; } catch (invalidkeyException e) {Throw New Exception ( "암호 해독 개인 키는 불법입니다."); } catch (불법 블록 시지 렉스 션 e) {새 예외를 던지십시오 ( "cryptotext 길이는 불법"); } catch (badpaddingException e) {Throw New Exception ( "cryptotext 데이터가 손상되었습니다"); }} / *** 바이트 데이터는 16 진수 문자열에 대한 바이트 데이터* @param 데이터 입력 데이터* @return hexadecimal content* / public static string bytearraytostring (byte [] data) {StringBuilder StringBuilder = new StringBuilder (); for (int i = 0; i <data.length; i ++) {// 바이트의 높은 4 자리 숫자를 색인으로 꺼내어 해당 16 진 식별자를 얻습니다. // 해당 16 진 식별자 stringBuilder.Append (HEX_CHAR [(data [i] & 0x0f)])를 얻기 위해 바이트의 낮은 4 비트를 색인으로 꺼냅니다. if (i <data.length-1) {StringBuilder.append ( ''); }} return stringBuilder.toString (); } public static void main (String [] args) {rsaencrypt rsaencrypt = new rsaencrypt (); //rsaencrypt.genkeypair (); // 공개 키를로드하십시오 {rsaencrypt.loadpublickey (rsaencrypt.default_public_key); System.out.println ( "공개 키로드"); } catch (예외 e) {System.err.println (e.getMessage ()); System.err.println ( "공개 키로드 실패"); } // 개인 키로드 시도 {rsaencrypt.loadprivatekey (rsaencrypt.default_private_key); System.out.println ( "개인 키로드"); } catch (예외 e) {System.err.println (e.getMessage ()); System.err.println ( "개인 키로로드 실패"); } // Test String String alcryptstr = "Test String Chaijunkun"; {// encrypt byte [] cipher = rsaencrypt.encrypt (rsaencrypt.getpublickey (), encryptstr.getBytes ()); // decrypt byte [] plaintext = rsaencrypt.decrypt (rsaencrypt.getprivatekey (), cipher); System.out.println ( "암호 텍스트 길이 :"+ cipher.length); System.out.println (rsaencrypt.bytearraytostring (cipher)); System.out.println ( "일반 텍스트 길이 :"+ plaintext.length); System.out.println (rsaencrypt.bytearraytostring (plaintext)); System.out.println (새 문자열 (일반 텍스트)); } catch (예외 e) {System.err.println (e.getMessage ()); }}} 코드에서는 공개 및 개인 키를로드하는 두 가지 방법을 제공합니다.
스트림 읽기 : Android 응용 프로그램에서 ID 인덱싱 리소스에 의해 입력 스트림을 얻는 방법에 적합합니다.
문자열별로 읽기 : 코드에 표시된대로 키 내용을 정적 상수에 선으로 저장하고 문자열 유형별로 키를 가져옵니다.
위의 코드를 실행하면 다음 정보가 표시됩니다.
1 64 57 C8 E3 46 A7 CE 57 31 AC CD 21 89 89 8F C1 24 C1 22 0C CB 70 6A 0D FA C9 38 80 BA 2E E1 29 02 ED 45 9E 88 E9 23 09 87 AD AB AC CB 61 03 3C A1 81 56 A5 DE C4 79 AA 3E 48 EE 30 3D BC 5BC 5BC 55 9F FD 22 87 9E DE B1 F4 E8 B2 일반 텍스트 길이 : 22 54 65 73 74 20 53 74 72 69 6E 67 20 63 68 61 69 6A 75 6E 6B 75 6E 테스트 문자열 chaijunkun
주요 함수에서 나는 "rsaencrypt.genkeypair ()"를 댓글을 달았으며, 이는 키 쌍을 무작위로 생성하는 데 사용됩니다 (생성, 사용, 저장이 아닌). 파일 키를 사용하지 않으면 키를로드 하거나이 메소드를 활성화하거나 코드를 실행하는 코드를 주석 할 수 있습니다.
공개 키를로드하는 것과 개인 키로드의 차이점은 공개 키가로드 될 때 x509encodedkeyspec (x509- 인코딩 된 키 명령어)와 개인 키가로드되면 PKCS8EncodedKeyspec (PKCS#8-Encoded 키 지침)입니다.
2012 년 2 월 22 일에 추가 : Android 소프트웨어 개발 중에 위의 코드가 제대로 작동하지 않는 것으로 나타났습니다. 주된 이유는 Sun.misc.base64decoder 클래스가 Android 개발 패키지에 존재하지 않기 때문입니다. 따라서 인터넷에서 Rt.jar의 소스 코드를 찾아야합니다. JDK의 src.zip의 소스 코드는 JDK의 소스 코드의 일부일 뿐이며 위의 클래스의 코드는 존재하지 않습니다. 검색 및 추가 후 위의 코드는 Android 응용 프로그램에서 잘 작동합니다. 여기에는이 클래스의 해당 코드가 포함되어 있습니다. 또한이 클래스는 CeformateXception, CestreamExhausted, Char
2012 년 2 월 23 일에 추가되었습니다. 처음에는이 기사를 작성하여 타사 패키지에 의존하지 않고 RSA 암호화 및 암호 해독을 구현하기 위해이 기사를 썼지 만 나중에 문제가 발생했습니다. 암호화 메소드 암호화와 해독 방법이 해독 된 암호화 객체를 만들어야 하므로이 객체는 GetInstance를 통해서만 인스턴스를 얻을 수 있습니다. IT의 두 가지 유형이 있습니다. 첫 번째는 제공자가 아닌 알고리즘 만 지정하는 것입니다. 두 번째는 둘 다 지정하는 것입니다. 처음에는 코드가 여전히 실행될 수 있지만 각 암호화의 결과가 다르다는 것을 알게됩니다. 나중에, 암호 객체가 사용하는 공개 및 개인 키는 코드에 지정된 공개 및 개인 키가 아니라 내부적으로 무작위로 생성 된 것으로 밝혀졌습니다. 이상하게도 제공자를 지정하지 않는이 코드는 Android 응용 프로그램을 통해 실행할 수 있으며 각 암호화 결과는 동일합니다. Android SDK의 일부 시스템 개발 기능 외에도 JDK의 기능도 구현한다고 생각합니다. 자체 JDK에 해당 공급자를 제공했을 수 있으며, 이는 매번 암호화 결과를 동일하게 만듭니다. 인터넷의 샘플 코드와 같은 바운시 캐슬 제공 업체를 추가하면 각 암호화 결과가 동일합니다.
읽어 주셔서 감사합니다. 도움이되기를 바랍니다. 이 사이트를 지원 해주셔서 감사합니다!