Overview and use RSA signature algorithm

First, the type of encryption algorithm

1, the key

      Key, typically a string or a number is passed to the encryption or decryption algorithm to encrypt or decrypt the time, so that the algorithm can correctly encrypt plaintext or decrypt ciphertext.

2, the encryption algorithm classification

        Generally classified as unidirectional and bidirectional encrypted encryption.

 2.1, one-way encryption

  Encryption is one way of non-reversible encryption, an encryption method is undecipherable, since it generates a unique encrypted encryption string, and therefore is often used to detect whether the data has been modified during transmission. Common one-way encryption has MD5, SHA, HMAC. We just use them as a basis for encryption, these three simple encryption is not reliable.

2.2, two-way encryption

  Way encryption can be divided into symmetric encryption and asymmetric encryption. You want encryption and decryption operations when the need to have two things: a secret key decryption algorithm and processing.

2.3, symmetric encryption

  Characteristics of symmetric encryption key and key algorithm is used to decrypt the encrypted using the same. In other words, the same key for encryption and decryption are used. Therefore, symmetric encryption algorithm to ensure the security of the case, the key natural to do security, can only let people use to know, not open to the public.

2.4 Asymmetric encryption

  In an asymmetric encryption algorithm, there are two kinds of public and private keys, wherein public key is published, does not require secrecy, the private key held by an individual, must be well kept and confidentiality. Encryption and decryption using two different keys, is the reason it its name. We estimated that we have heard about RSA, which is a common, very wide application of asymmetric encryption algorithms.

Two, RSA

1, What is that RSA is it?

RSA encryption algorithm is an asymmetric encryption algorithm , called asymmetric, meaning that the algorithm requires a pair of keys, using one of the encryption, decryption needs to another. This can be directly transmitted without the key, the decryption is completed. This can ensure the security of information, to avoid the risk of break caused by direct transfer key. The process is carried out by a pair of encryption and decryption keys, called the public key and private key, respectively. There are mathematical correlation between the two, the principles of the encryption algorithm is to do a great difficulty of integer factorization to ensure safety. Save usually private individuals, public key is (probably more than at the same time holding).

2, the principle

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

3, RSA encryption, signature difference

  Encryption and signature are for security reasons, but slightly different. People often ask is encrypted and signed with the private key or public? In fact be confusing for encryption and signature role. Simply put, encryption is to prevent the information from being leaked, and the signature is to prevent information being tampered with. To give two examples.

  The first scenario: the battlefield, B A delivery give a message instruction for a content.

  RSA encryption process is as follows:

  (1) A generates a pair of keys (public and private), the private key is not disclosed, A own reservation. The public key is public, anyone can get.

  (2) A transfer its public key to B, B with A's public key to encrypt the message.

  (. 3) A to B receives the encrypted message, decrypts the message using its private key A.

   In this process, only the secondary transfer process, the first public key is transmitted to A B, B is the second encrypted message is transmitted to the A, even if the enemy are intercepted, there is no danger, because the only A private key to decrypt the message, to prevent the disclosure of message content.

 

  The second scenario: A receives the message B sent, the need for reply "receive."

  RSA signature process is as follows:

  (1) A generates a pair of keys (public and private), the private key is not disclosed, A own reservation. The public key is public, anyone can get.

  (2) A plus sign with its private key of the message, a signature is formed, and an endorsement messages and messages to itself along B.

  After (3) B receives the message, Public Key A acquired in the test check, to check if the test message is consistent with the content out of itself, prove A message is a reply.

   In this process, only the secondary transfer process, the first transmission plus the A signed message and the message itself to B, B is a second A public key acquired, even if the enemy are intercepted, there is no danger, because only the private key of a can sign the message, even if they know the content of the message, you can not forge a signed reply to B, to prevent tampering with the content of the message.

        However, you will find a comprehensive two scenarios, although the first scene was intercepted messages did not reveal, but can be used to intercept public key to encrypt the false command, and then passed to A. Although the second scenario intercepted message can not be tampered with, but the content of the message using the public key can verify signed to obtain, and can not prevent leakage. Therefore, in practical applications, according to the case of using, encryption and signatures may be used simultaneously, such as A and B has a set of its own public key and private, when B sends message A to give, first with the public key to B message encryption, and then use a to a message encrypted private key signature, the reach is neither disclose nor been tampered with, we can guarantee the security of the message.

   Summary: public key encryption, private key to decrypt the private key signature, public key inspection sign.

Third, the test code

RSAUtil Tools


public class RsaUtil {

   /**

    * RSA encryption plaintext maximum size

    */

   private static final int MAX_ENCRYPT_BLOCK = 117;

   /**

    * RSA decrypt the ciphertext maximum size

    */

   private static final int MAX_DECRYPT_BLOCK = 128;

 

   public static final String privateKeyA = "privateKeyA";

   public static final String publicKeyA = "publicKeyA";

   public static final String publicKeyB = "publicKeyB";

   public static final String privateKeyB = "privateKeyB";

 

   /**

    * Get the private key

    * @Param privateKey private string

    * @return PrivateKey

    */

   public static PrivateKey getPrivateKey(String privateKey) throws Exception {

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

       byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());

       PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);

       return keyFactory.generatePrivate(keySpec);

   }

   /**

    * Get the public key

    * @Param publicKey public string

    * @return PublicKey

    */

   public static PublicKey getPublicKey(String publicKey) throws Exception {

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

       byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());

       X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);

       return keyFactory.generatePublic(keySpec);

   }

   /**

    * Randomly generated key pair

    * @throws NoSuchAlgorithmException

    */

   public static Map<Integer,String> genKeyPair() throws NoSuchAlgorithmException {

       // KeyPairGenerator class for generating public and private keys to generate the object based on the RSA algorithm

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

       // Initializes the key pair generator, a key size of 96-1024 bit

       keyPairGen.initialize(1024,new SecureRandom());

       // generate a key pair is stored in the keyPair

       KeyPair keyPair = keyPairGen.generateKeyPair();

       RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate (); // secret key

       RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic (); // get the public key

       String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));

       // get the private key string

       String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));

       // Save the public and private keys to the Map

       Map<Integer, String> keyMap = new HashMap();

       keyMap.put (0, publicKeyString); // 0 represents a public key

       keyMap.put (1, privateKeyString); // 1 represents the private key

       return keyMap;

   }

   /**

    * RSA public key encryption

    * @Param str encrypted string

    * @Param publicKey public

    * @Return ciphertext

    * @Throws Exception exception message encryption process

    */

   public static String encrypt( String str, String publicKey ) throws Exception{

       // base64 encoded public key

       byte[] decoded = Base64.decodeBase64(publicKey);

       RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));

       // RSA encryption

       Cipher cipher = Cipher.getInstance("RSA");

       cipher.init(Cipher.ENCRYPT_MODE, pubKey);

       byte[] data = str.getBytes("UTF-8");

       int inputLen = data.length;

       ByteArrayOutputStream out = new ByteArrayOutputStream();

       int offSet = 0;

       byte[] cache;

       int i = 0;

       // to encrypt data segments

       while (inputLen - offSet > 0) {

           if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {

               cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);

           } else {

               cache = cipher.doFinal(data, offSet, inputLen - offSet);

           }

           out.write(cache, 0, cache.length);

           i++;

           offSet = i * MAX_ENCRYPT_BLOCK;

       }

       byte[] encryptedData = out.toByteArray();

       out.close();

       String outStr = Base64.encodeBase64String(encryptedData);

       return outStr;

   }

   /**

    * RSA private key to decrypt

    * @Param str encrypted string

    * @Param privateKey private

    * @Return inscriptions

    * @Throws Exception exception message decryption process

    */

   public static String decrypt(String str, String privateKey) throws Exception{

       // 64-bit decoded encrypted string

       byte[] data = Base64.decodeBase64(str.getBytes("UTF-8"));

       // base64-encoded private key

       byte[] decoded = Base64.decodeBase64(privateKey);

       RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));

       // RSA decryption

       Cipher cipher = Cipher.getInstance("RSA");

       cipher.init(Cipher.DECRYPT_MODE, priKey);

       int inputLen = data.length;

       ByteArrayOutputStream out = new ByteArrayOutputStream();

       int offSet = 0;

       byte[] cache;

       int i = 0;

       // to decrypt the data segments

       while (inputLen - offSet > 0) {

           if (inputLen - offSet > MAX_DECRYPT_BLOCK) {

               cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);

           } else {

               cache = cipher.doFinal(data, offSet, inputLen - offSet);

           }

           out.write(cache, 0, cache.length);

           i++;

           offSet = i * MAX_DECRYPT_BLOCK;

       }

       byte[] decryptedData = out.toByteArray();

       out.close();

       String outStr = new String(decryptedData);

       return outStr;

   }

        /**

         * Signed

         * @Param data data to be signed

         * @Param privateKey private

         * @Return signature

         */

        public static String sign(String data, PrivateKey privateKey) throws Exception {

            byte[] keyBytes = privateKey.getEncoded();

            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

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

            PrivateKey key = keyFactory.generatePrivate (keySpec);

            Signature signature = Signature.getInstance("MD5withRSA");

            signature.initSign(key);

            signature.update(data.getBytes());

            return new String(Base64.encodeBase64(signature.sign()));

        }

       /**

        * Verification sign

        * @Param srcData original string

        * @Param publicKey public

        * @Param sign signature

        * @Return whether by check inspection

        */

       public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {

           byte[] keyBytes = publicKey.getEncoded();

           X509EncodedKeySpec keySpec = new X509EncodedKeySpec (keyBytes);

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

           PublicKey key = keyFactory.generatePublic(keySpec);

           Signature signature = Signature.getInstance("MD5withRSA");

           signature.initVerify(key);

           signature.update(srcData.getBytes());

           return signature.verify(Base64.decodeBase64(sign.getBytes()));

       }

}

 

Test class client

Suppose generate two pairs of public, private, as the tools in order to use the following

 

public class TestClient {

   public static void main(String[] args) {

A server is a // client B

// test sign ();

//        testPassword();

       testSignAndPassword ();

   }

   public static void testPassword(){

       Test Server test server = new test server ();

       try {

           PasswordOrder passwordOrder = new PasswordOrder("1",new BigDecimal(100),"描述信息","weixin");

           System.out.println ( "data before encryption:" + JSONObject.toJSONString (passwordOrder));

           String encrypt = RsaUtil.encrypt(JSONObject.toJSONString(passwordOrder), RsaUtil.publicKeyA);

           System.out.println ( "encrypted data:" + encrypt);

           testServer.testPassword (encrypt);

       } catch (Exception e){

           e.printStackTrace ();

       }

   }

   public static void testSign(){

       try {

           Test Server test server = new test server ();

           ClientOrder order = new ClientOrder ( "1", new BigDecimal (100), "description", "weixin");

           String data = MapUtil.mapToString (MapUtil.beanToMap (order));

           String sign = RsaUtil.sign(data, RsaUtil.getPrivateKey(RsaUtil.privateKeyA));

           order.setSign(sign);

           System.out.println ( "client request data to the original data and sign:" + JSONObject.toJSONString (order));

           testServer.testSign (order);

       } catch (Exception e){

           e.printStackTrace ();

       }

   }

   /**

    * After the first signature and encrypts the ciphertext spread to the server

    */

   public static void testSignAndPassword(){

       try {

           Test Server test server = new test server ();

           ClientOrder order = new ClientOrder ( "1", new BigDecimal (100), "description", "weixin");

           String data = MapUtil.mapToString (MapUtil.beanToMap (order));

           String sign = RsaUtil.sign(data, RsaUtil.getPrivateKey(RsaUtil.privateKeyA));

           order.setSign(sign);

           System.out.println ( "Signed:" + sign);

           System.out.println ( "data before encryption:" + JSONObject.toJSONString (order));

           String encrypt = RsaUtil.encrypt(JSONObject.toJSONString(order), RsaUtil.publicKeyB);

           System.out.println ( "encrypted data:" + encrypt);

           testServer.testSignAndPassword (encrypt);

       } catch (Exception e){

           e.printStackTrace ();

       }

   }

}

 

Test class server

public class TestServer {

   public void testSign(ClientOrder order){

       try {

           System.out.println ( "Received Data server:" + JSONObject.toJSONString (order));

           String sign = order.getSign();

           order.setSign(null);

           String data = MapUtil.mapToString (MapUtil.beanToMap (order));

           boolean verify = RsaUtil.verify(data, RsaUtil.getPublicKey(RsaUtil.publicKeyA), sign);

           System.out.println ( "test ballot results:" + verify);

       } catch (Exception e){

           e.printStackTrace ();

       }

   }

   public void testPassword(String encrypt) {

       try {

           String decrypt = RsaUtil.decrypt(encrypt, RsaUtil.privateKeyA);

           PasswordOrder passwordOrder = JSONObject.parseObject(decrypt, PasswordOrder.class);

           System.out.println ( "decrypted data:" + JSONObject.toJSONString (passwordOrder));

       } catch (Exception e){

           e.printStackTrace ();

       }

   }

   /**

    * Decrypt, sign and then inspection

    * @param encrypt

    */

   public void testSignAndPassword(String encrypt) {

       try {

           System.out.println ( "Data Received:" + encrypt);

           String decrypt = RsaUtil.decrypt(encrypt, RsaUtil.privateKeyB);

           System.out.println ( "decrypted data:" + decrypt);

           ClientOrder clientOrder = JSONObject.parseObject(decrypt, ClientOrder.class);

           String sign = clientOrder.getSign();

           clientOrder.setSign(null);

           String data = MapUtil.mapToString (MapUtil.beanToMap (clientOrder));

           boolean verify = RsaUtil.verify(data, RsaUtil.getPublicKey(RsaUtil.publicKeyA), sign);

           System.out.println ( "test ballot results:" + verify);

       } catch (Exception e){

           e.printStackTrace ();

       }

   }

}

 

note:

  1, because when rsa encryption and decryption, there is a length limit, when it should be used in the encryption and decryption segmented.

  2, when the encryption and decryption needs to use the time after the first signature encryption must be assumed that the request B is A, A signature generated with the private key of A, then B, public key encryption, the final pass ciphertext B, B received when the ciphertext, is decrypted with the private key of B, then a is signed public inspection.

 

 scenes to be used:

  1, only the data is encrypted, then the server side need only generate a pair of public and private key, public key to Client, mainly used in this case interact with the web server, such as a password or the like pass. (Anti-leakage)

  2, only the sign data, only this time the client side generates a pair of public and private key, public key to the server, this is mainly used within the company and to third mating, for example, the company has access required items A micro-channel Alipay, Jingdong, ie, A is a client, it is a third party server, so every time after a third-party call requires the signature data, to third parties, and then to carry out inspection sign. (Tamper proof)

  3, the data is signed and encrypted, then both client and server each generate a pair of public and private key, a public key exchange, this is mainly used in the data transfer between the enterprises, such as methyl acetate two companies to communicate. (Tamper-proof and leak-proof)

 

These are reference data and their own income, subject to the original, please understand!

Guess you like

Origin www.cnblogs.com/longyao/p/11346984.html