개요 및 RSA 서명 알고리즘을 사용

암호화 알고리즘 우선 형식

1 키

      키, 일반적으로는 문자열 또는 숫자 알고리즘이 제대로 일반 텍스트를 암호화하거나 암호문을 해독 할 수 있도록 암호화하거나 시간을 해독하기 위해 암호화 또는 암호 해독 알고리즘에 전달됩니다.

제 2 암호 알고리즘 구분

        일반적으로 단방향 및 양방향 암호화 된 암호화로 분류.

 2.1 단방향 암호화

  암호화는 암호화 된 암호화 고유 문자열을 생성하며, 따라서 종종 데이터가 전송 동안 수정되지 않았는지 여부를 검출하기 위해 사용되기 때문에, 비가역적인 암호화 방법 중 하나는, 암호화 방법, 해독 할이다. 일반적인 단방향 암호화는 MD5, SHA, HMAC이있다. 우리는 단지 암호화를위한 기초로 사용,이 세 가지 간단한 암호화는 신뢰할 수 없습니다.

2.2 양방향 암호화

  웨이 암호화는 대칭 암호화와 비대칭 암호화로 나눌 수 있습니다. 비밀 키 암호 해독 알고리즘과 처리 : 필요 두 가지를 가질 때 암호화 및 암호 해독 작업을 할 수 있습니다.

2.3 대칭 암호화

  대칭 암호화 키 및 키 알고리즘의 특성은 동일하게 사용하여 암호화 해독하는 데 사용된다. 즉, 암호화 및 암호 해독에 동일한 키가 사용됩니다. 따라서 대칭 암호화 알고리즘이 사건의 보안을 보장하기 위해, 키 자연해야 할 보안은 단지 사람들이 대중에게 열려 있지 알고 사용하도록 할 수 있습니다.

2.4 비대칭 암호화

  비대칭 암호화 알고리즘에서, 공개 키가 공개되는 공개 키와 개인 키의 두 종류가 있습니다, 비밀을 필요로하지 않습니다, 개인이 보유한 개인 키는 잘 보관하고 기밀 유지해야합니다. 암호화 및 두 개의 서로 다른 키를 사용하여 복호화, 이유는 그것에게 그것의 이름입니다. 우리는 우리가 비대칭 암호화 알고리즘의 일반적인, 매우 넓은 응용 프로그램입니다 RSA에 대해 들었을 것으로 추정.

두, RSA

1, RSA는 그것을이다 무엇입니까?

RSA 암호 알고리즘은 비대칭 암호 알고리즘 은 암호화 한 복호화 다른 필요하여, 알고리즘은 한 쌍의 키를 필요로한다는 것을 의미 비대칭이라고. 이것은 직접 키없이 전송 될 수 있으며, 암호 해독이 완료됩니다. 이것은 직접 전송 키에 의한 중단의 위험을 방지하기 위해, 정보의 보안을 보장 할 수 있습니다. 이 과정은 각각 공개 키와 개인 키라고하는 암호화 및 복호화 키의 쌍에 의해 수행된다. 둘 사이의 수학적 상관 관계가있다, 암호 알고리즘의 원리는 안전을 보장하기 위해 정수 인수 분해의 큰 어려움을하는 것입니다. 일반적으로 개인이를 저장, 공개 키 (같은 시간 (HOLD)보다 아마 더)입니다.

2, 원칙

http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html

3, RSA 암호화, 서명 차이

  암호화 및 서명은 보안상의 이유로,하지만 약간 다른. 사람들은 종종 암호화와 개인 키 또는 공개로 서명 물어도 될까요? 실제로 암호화 및 서명 역할에 대한 혼란. 간단히 말해, 암호화가 유출되는 정보를 방지하기 위해, 그리고 서명 정보가 훼손되는 것을 방지하기위한 것입니다. 두 가지 예를 제공합니다.

  첫 번째 시나리오 : 전장은 B 배달은 콘텐츠에 대한 메시지 명령을 제공합니다.

  다음과 같이 RSA 암호화 프로세스는 다음과 같습니다

  (1)은 키 쌍 (공개 키와 개인 키)를 비밀 키 전용하는 자신의 예약을 생성한다. 공개 키는 공개, 누구나 얻을 수 있습니다.

  (2)의 공개 키와 함께 전송하는 B의 공개 키 B는 메시지를 암호화한다.

  . (3)에 대한 B는 암호화 된 메시지를 수신하여 자신의 개인 키 A를 사용하여 메시지를 복호화

   이 과정 만 차 전사 공정, 제 1 공개 키는 B에 송신에서, B는 위험이 없다 번째 암호화 된 메시지가 적을 차단 되더라도 상기 (A)에 전달 된 경우에만 개인 때문에 메시지 내용의 공개를 방지하기 위해, 메시지의 암호를 해독 할 키를 누릅니다.

 

  두 번째 시나리오는 : A는 B가 보낸 메시지, 응답에 대한 필요성 수신 "수신을."

  다음과 같이 RSA 서명 프로세스는 다음과 같습니다

  (1)은 키 쌍 (공개 키와 개인 키)를 비밀 키 전용하는 자신의 예약을 생성한다. 공개 키는 공개, 누구나 얻을 수 있습니다.

  (2) 플러스 메시지는 개인 키 서명은 서명 B. 따라 자체적으로 승인 메시지와 메시지를 형성하고,

  (3) B가 메시지를 수신 한 후, 공개 키 A는 테스트 메시지 자체의 출력 내용과 일치하는지 확인하기 위해 시험 검사에 인수 메시지가 응답 증명.

   이 과정에서, 단지 차 전사 프로세스, 제 1 송신 플러스 A는 메시지를 서명 및 메시지 자체 B로, B는 획득 한 두 번째 공개 키이고, 적의가 차단 된 경우에도 위험이없는, 의 개인 키가 메시지의 내용을 알고있는 경우에도 메시지에 서명 할 수 있기 때문에, 당신은 메시지의 내용과 변조 방지하기 위해, B에 서명 답장을 위조 할 수 없다.

        첫 번째 장면이 메시지는 공개하지 않았다 차단했지만, 거짓 명령을 암호화하는 공개 키를 차단하는 데 사용할 수있는 다음 A.에 전달하지만, 그러나, 포괄적 인 두 가지 시나리오를 찾을 수 두 번째 시나리오는 차단했지만 메시지를 위조 할 수는 없지만, 공개 키를 사용하여 메시지의 내용 얻기 위해 서명 확인할 수 있습니다, 누출을 방지 할 수 없습니다. 따라서, 실용에 이용하는 경우에있어서, 암호화 및 서명 등으로 동시에 사용될 수 있고, B는 메시지 A가 수득 보내면 B는 제 B의 공개 키, 공개 키와 개인 키의 고유의 세트를 갖는다 메시지 암호화는 다음 메시지에 암호화 된 개인 키 서명을를 사용, 범위는 어느 쪽도 공개하거나 위조 된, 우리는 메시지의 보안을 보장 할 수있다.

   요약 : 공개 키 암호화, 개인 키는 개인 키 서명, 공개 키 검사 기호를 해독한다.

셋째, 테스트 코드

RSAUtil 도구


공용 클래스 RsaUtil {

   / **

    * RSA 암호화 평문 최대 크기

    * /

   개인 정적 최종 INT의 MAX_ENCRYPT_BLOCK = 117;

   / **

    * RSA 암호문 최대 크기를 해독

    * /

   개인 정적 최종 INT의 MAX_DECRYPT_BLOCK = 128;

 

   공공 정적 마지막 문자열 privateKeyA = "privateKeyA";

   공공 정적 최종 문자열 publicKeyA = "publicKeyA";

   공공 정적 마지막 문자열 publicKeyB = "publicKeyB";

   공공 정적 최종 문자열 privateKeyB = "privateKeyB";

 

   / **

    * 개인 키를 가져옵니다

    파라미터 : PrivateKey의 개인 문자열

    * @return의 PrivateKey

    * /

   공공 정적의 PrivateKey getPrivateKey (문자열의 PrivateKey)는 예외 {던졌습니다

       KeyFactory에 KeyFactory에 KeyFactory.getInstance = ( "RSA");

       바이트의 [] = decodedKey Base64.decodeBase64 (privateKey.getBytes ());

       PKCS8EncodedKeySpec를 keySpec에 새로운 PKCS8EncodedKeySpec를 = (decodedKey);

       keyFactory.generatePrivate (keySpec에)를 리턴;

   }

   / **

    * 공개 키를 가져옵니다

    파라미터 : 공개 키 공공 문자열

    * @return의 한 PublicKey

    * /

   공공 정적의 PublicKey의 getpublickey (문자열 공개 키)는 예외 {던졌습니다

       KeyFactory에 KeyFactory에 KeyFactory.getInstance = ( "RSA");

       바이트 [] = decodedKey Base64.decodeBase64 (publicKey.getBytes ());

       X509EncodedKeySpec를 keySpec에 새로운 X509EncodedKeySpec를 = (decodedKey);

       keyFactory.generatePublic (keySpec에)을 반환;

   }

   / **

    * 무작위로 생성 된 키 쌍

    * 예외 : NoSuchAlgorithmException를 @throws

    * /

   공공 정적지도 <정수, 문자열> genKeyPair ()이 예외 : NoSuchAlgorithmException를 {던졌습니다

       RSA 알고리즘에 기초하여 객체를 생성하는 공개 키와 개인 키를 생성 // KeyPairGenerator의 클래스

       KeyPairGenerator의 keyPairGen = KeyPairGenerator.getInstance ( "RSA");

       // 키 쌍 생성기 96-1024 비트의 키 크기를 초기화

       keyPairGen.initialize (1024, 새로운 SecureRandom의 ());

       // 키 쌍이 키 쌍 생성에 저장된

       된 KeyPair 키쌍 keyPairGen.generateKeyPair = ();

       RSAPrivateKey의 PrivateKey = (RSAPrivateKey) keyPair.getPrivate (); // 비밀 키

       RSAPublicKey 공개 키 = (RSAPublicKey) keyPair.getPublic (); // 공개 키를 얻을 수

       문자열 publicKeyString = 새로운 String (Base64.encodeBase64 (publicKey.getEncoded ()));

       // 개인 키 문자열을 얻을

       문자열 privateKeyString = 새로운 String (Base64.encodeBase64 ((privateKey.getEncoded ())));

       //지도에 공개 키와 개인 키를 저장

       지도 <정수, 문자열> 키 맵 = 새의 HashMap ();

       keyMap.put (0, publicKeyString); // 0은 공개 키를 나타냅니다

       keyMap.put (1 privateKeyString); // 1 개인 키를 나타낸다

       키 맵을 반환;

   }

   / **

    * RSA 공개 키 암호화

    파라미터 : STR 암호화 된 문자열

    파라미터 : 공개 키 공개

    * @return의 암호문

    * @throws 예외 예외 메시지 암호화 프로세스

    * /

   공공 정적 문자열 암호화는 (문자열 STR은 문자열 공개 키)는 예외 {던졌습니다

       // base64로 인코딩 된 공개 키

       바이트 [] = Base64.decodeBase64 (공개 키) 디코딩;

       RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance ( "RSA")의 generatePublic (새 X509EncodedKeySpec를 (복호화)).;

       // RSA 암호화

       암호화 암호 = Cipher.getInstance ( "RSA");

       cipher.init (Cipher.ENCRYPT_MODE, pubKey);

       바이트 []의 데이터 = str.getBytes ( "UTF-8");

       INT의 inputLen = data.length입니다;

       () = 새로운있는 ByteArrayOutputStream을있는 ByteArrayOutputStream;

       INT는 오프셋 = 0;

       바이트 [] 캐시;

       int로 I = 0;

       // 데이터 세그먼트를 암호화

       (의 inputLen -> 오프셋 0) {동안

           경우 (의 inputLen -의 offSet> MAX_ENCRYPT_BLOCK) {

               캐시 cipher.doFinal = (데이터, MAX_ENCRYPT_BLOCK의 offSet);

           } 다른 {

               캐시 cipher.doFinal = (데이터 옵셋의 inputLen -의 offSet);

           }

           out.write (캐시 0 cache.length);

           내가 ++;

           = OFFSET 난을 MAX_ENCRYPT_BLOCK *;

       }

       바이트 []의 EncryptedData out.toByteArray = ();

       out.close ();

       문자열 outstr에 Base64.encodeBase64String = (의 EncryptedData);

       outstr에 반환;

   }

   / **

    * RSA 개인 키의 암호를 해독하기

    파라미터 : STR 암호화 된 문자열

    파라미터 : PrivateKey의 개인

    * @return 비문

    * @throws 예외 예외 메시지 복호화 프로세스

    * /

   공공 정적 문자열 해독은 (문자열 STR은 문자열의 PrivateKey)는 예외 {던졌습니다

       // 64 비트 암호화 된 문자열을 디코드

       바이트 [] = 데이터의 Base64.decodeBase64 (str.getBytes ( "UTF-8"));

       // base64로 인코딩 된 개인 키

       바이트 [] = Base64.decodeBase64 (의 PrivateKey) 디코딩;

       RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance ( "RSA") generatePrivate (새 PKCS8EncodedKeySpec를 (복호화)).;

       // RSA 암호 해독

       암호화 암호 = Cipher.getInstance ( "RSA");

       cipher.init (cipher를 Cipher.DECRYPT_MODE, priKey);

       INT의 inputLen = data.length입니다;

       () = 새로운있는 ByteArrayOutputStream을있는 ByteArrayOutputStream;

       INT는 오프셋 = 0;

       바이트 [] 캐시;

       int로 I = 0;

       // 데이터 세그먼트를 해독

       (의 inputLen -> 오프셋 0) {동안

           경우 (의 inputLen -의 offSet> MAX_DECRYPT_BLOCK) {

               캐시 cipher.doFinal = (데이터, MAX_DECRYPT_BLOCK의 offSet);

           } 다른 {

               캐시 cipher.doFinal = (데이터 옵셋의 inputLen -의 offSet);

           }

           out.write (캐시 0 cache.length);

           내가 ++;

           = OFFSET 난을 MAX_DECRYPT_BLOCK *;

       }

       바이트 [] = decryptedData out.toByteArray ();

       out.close ();

       문자열 outstr에 = 새로운 String (decryptedData);

       outstr에 반환;

   }

        / **

         * 서명

         파라미터 : 데이터 데이터에 서명한다

         파라미터 : PrivateKey의 개인

         * @return 서명

         * /

        공공 정적 문자열 기호 (문자열 데이터의 PrivateKey의 PrivateKey)는 예외 {던졌습니다

            바이트 [] = keyBytes privateKey.getEncoded ();

            PKCS8EncodedKeySpec를 keySpec에 새로운 PKCS8EncodedKeySpec를 = (keyBytes);

            KeyFactory에 KeyFactory에 KeyFactory.getInstance = ( "RSA");

            키의 PrivateKey = keyFactory.generatePrivate (keySpec에);

            서명 서명 = Signature.getInstance ( "MD5withRSA가");

            signature.initSign (키);

            signature.update (data.getBytes ());

            새로운 String을 반환 (Base64.encodeBase64 (signature.sign ()));

        }

       / **

        * 확인 서명

        파라미터 : srcData 원래 문자열

        파라미터 : 공개 키 공개

        파라미터 : 기호 서명

        * @return 확인 검사에 의해 여부

        * /

       공공 정적 부울 (문자열 srcData, PublicKey의 공개 키, 문자열 기호) 확인은 예외 {던졌습니다

           바이트 [] = keyBytes publicKey.getEncoded ();

           X509EncodedKeySpec를 keySpec에 새로운 X509EncodedKeySpec를 = (keyBytes);

           KeyFactory에 KeyFactory에 KeyFactory.getInstance = ( 「RSA ");

           PublicKey의 키 = keyFactory.generatePublic (keySpec에);

           서명 서명 = Signature.getInstance ( "MD5withRSA가");

           signature.initVerify (키);

           signature.update (srcData.getBytes ());

           signature.verify 반환 (Base64.decodeBase64 (sign.getBytes ()));

       }

}

 

테스트 클래스 클라이언트

사용하기 위해 다음 도구 등 공공, 민간 두 쌍을 생성한다고 가정

 

공용 클래스 TestClient을 {

   공공 정적 무효 메인 (문자열 []에 args) {

서버는 // 클라이언트 B입니다

// 테스트 기호 ();

// testPassword이다 ();

       testSignAndPassword ();

   }

   공공 정적 무효 testPassword이다 () {

       테스트 서버 테스트 서버 = 새로운 테스트 서버 ();

       {시도

           PasswordOrder passwordOrder = 새로운 PasswordOrder ( 「1」, 새로운 BigDecimal를 (100), "描述 信息", "weixin");

           에서 System.out.println ( "암호화 전에 데이터의"+ JSONObject.toJSONString (passwordOrder));

           문자열을 암호화 = RsaUtil.encrypt (JSONObject.toJSONString (passwordOrder), RsaUtil.publicKeyA);

           에서 System.out.println ( "암호화 데이터"암호화 +);

           testServer.testPassword (암호화);

       } 캐치 (예외 전자) {

           e.printStackTrace ();

       }

   }

   공공 정적 무효 testSign () {

       {시도

           테스트 서버 테스트 서버 = 새로운 테스트 서버 ();

           ClientOrder 위해 새로운 ClientOrder = ( 「1」, 새로운 BigDecimal를 (100), "설명", "weixin");

           문자열 데이터 = MapUtil.mapToString (MapUtil.beanToMap (순서));

           문자열 기호 = RsaUtil.sign (데이터, RsaUtil.getPrivateKey (RsaUtil.privateKeyA));

           order.setSign (기호);

           에서 System.out.println ( "원본 데이터에 대한 클라이언트 요청 데이터와 서명 :"+ JSONObject.toJSONString (위해));

           testServer.testSign (순서대로);

       } 캐치 (예외 전자) {

           e.printStackTrace ();

       }

   }

   / **

    * 제 서명 후 서버 암호문 확산 암호화

    * /

   공공 정적 무효 testSignAndPassword () {

       {시도

           테스트 서버 테스트 서버 = 새로운 테스트 서버 ();

           ClientOrder 위해 새로운 ClientOrder = ( 「1」, 새로운 BigDecimal를 (100), "설명", "weixin");

           문자열 데이터 = MapUtil.mapToString (MapUtil.beanToMap (순서));

           문자열 기호 = RsaUtil.sign (데이터, RsaUtil.getPrivateKey (RsaUtil.privateKeyA));

           order.setSign (기호);

           에서 System.out.println는 ( "서명 :"+ 기호);

           에서 System.out.println ( "데이터를 암호화하기 전에"+ JSONObject.toJSONString (순서));

           문자열 암호화 = RsaUtil.encrypt (JSONObject.toJSONString (순서) RsaUtil.publicKeyB);

           에서 System.out.println ( "암호화 데이터"암호화 +);

           testServer.testSignAndPassword (암호화);

       } 캐치 (예외 전자) {

           e.printStackTrace ();

       }

   }

}

 

테스트 클래스 서버

공용 클래스 TESTSERVER {

   공공 무효 testSign (ClientOrder 순서) {

       {시도

           에서 System.out.println ( "수신 된 데이터 서버 :"+ JSONObject.toJSONString (위해));

           문자열 기호 = order.getSign ();

           order.setSign (NULL);

           문자열 데이터 = MapUtil.mapToString (MapUtil.beanToMap (순서));

           RsaUtil.verify = (데이터 RsaUtil.getPublicKey (RsaUtil.publicKeyA) 부호)를 확인하는 부울 (Boolean) :

           에서 System.out.println ( "시험 투표 결과 :"+ 확인)

       } 캐치 (예외 전자) {

           e.printStackTrace ();

       }

   }

   공공 무효 testPassword이다 (문자열 암호화) {

       {시도

           문자열 해독 = RsaUtil.decrypt (암호화, RsaUtil.privateKeyA);

           PasswordOrder passwordOrder = JSONObject.parseObject (PasswordOrder.class 해독);

           에서 System.out.println ( "해독 데이터"+ JSONObject.toJSONString (passwordOrder));

       } 캐치 (예외 전자) {

           e.printStackTrace ();

       }

   }

   / **

    * 해독, 서명 한 후 검사

    파라미터 : 암호화

    * /

   공공 무효 testSignAndPassword (문자열 암호화) {

       {시도

           에서 System.out.println ( "데이터 수신 :"+ 암호화);

           문자열 해독 = RsaUtil.decrypt (암호화, RsaUtil.privateKeyB);

           에서 System.out.println ( "데이터를 해독"해독 +);

           ClientOrder clientOrder = JSONObject.parseObject (ClientOrder.class 해독);

           문자열 기호 = clientOrder.getSign ();

           clientOrder.setSign (NULL);

           문자열 데이터 = MapUtil.mapToString (MapUtil.beanToMap (clientOrder));

           RsaUtil.verify = (데이터 RsaUtil.getPublicKey (RsaUtil.publicKeyA) 부호)를 확인하는 부울 (Boolean) :

           에서 System.out.println ( "시험 투표 결과 :"+ 확인)

       } 캐치 (예외 전자) {

           e.printStackTrace ();

       }

   }

}

 

참고 :

  (1)이 분할 된 암호화 및 복호화에 사용되어야 할 때 RSA 암호화 및 복호화는, 길이 제한이있는 경우 때문이다.

  암호화 및 암호 해독의 제 1 서명의 암호화가 요구 B가 (A)의 개인 키를 사용하여 생성 된 A, 서명이라고 가정한다 후 시간을 사용할 필요가 2, 그 다음 B는, 공개 키 암호, 최종 패스 암호문 B는 B받은 암호문은, B의 개인 키로 복호화 할 때, 다음, 공공 검사 서명됩니다.

 

 사용 시나리오 :

  1 데이터 만이 암호화되고, 서버 측에만 주로 패스워드 등 패스로, 웹 서버와 상호 작용이 경우에 사용되는 공개 키와 개인 키, 클라이언트 공개 키의 페어를 생성 할 필요가있다. (안티 - 누설)

  2 만 부호 데이터 만이 시간은 클라이언트 측에서 공개 키 및 개인 키 쌍을 생성하고, 서버에 대한 공개 키는, 이것은 주로 회사 내와 제 결합에 사용, 예를 들어, 회사가 마이크로 채널 액세스에 필요한 항목이 Alipay의, Jingdong, 즉, A는 그렇게 때마다 제 3 자 호출 한 후 타사에 데이터 서명을 필요로하고 검사 서명을 수행하기 위해, 타사 서버입니다, 클라이언트입니다. (탬퍼 증거)

  (3)은, 데이터가 서명되고 암호화되고, 각각의 공개 및 비밀 키, 공개 키를 교환 한 쌍을 생성하는 클라이언트 및 서버는, 이는 주로 통신하는 메틸 아세테이트 양사 같이 기업 간의 데이터 전송에 사용된다. (탬퍼 및 새지)

 

다음은 참고 자료이며, 원래의 대상이 자신의 소득, 양해 바랍니다!

추천

출처www.cnblogs.com/longyao/p/11346984.html