Two encryption algorithms must be used in Android network transmission: MD5 and RSA

MD5 and RSA are the two most commonly used algorithms in network transmission. After understanding the principles of these two algorithms, you can roughly know what encryption is all about. However, these two algorithms have different usage environments and are just complementary.

1. MD5 algorithm

First of all, MD5 is irreversible and can only be encrypted but not decrypted. For example, the plaintext is yanzi1225627, and the MD5-encrypted string is: 14F2AE15259E2C276A095E7394DA0CA9, but yanzi1225627 cannot be deduced from the latter string. Therefore, it can be used to store the password entered by the user on the server. Now it is also used to download the file to check whether the file has been tampered with. For the principle, see: http://blog.csdn.net/forgotaboutgirl/article/details/7258109 It is easier to implement MD5 in Java  on Android or PC. Because java has done it in java.security.MessageDigest. Here is an MD5Util.java class:

package org.md5.util;  
  
import java.security.MessageDigest;  
public class MD5Util {  
    public final static String getMD5String(String s) {  
        char hexDigits[] = { '0', '1', '2', '3', '4',  
                '5', '6', '7', '8', '9',  
                'A', 'B', 'C', 'D', 'E', 'F' };  
        try {  
            byte[] btInput = s.getBytes();  
            //Get the MessageDigest object of the MD5 digest algorithm  
            MessageDigest mdInst = MessageDigest.getInstance("MD5");  
            //Update the digest with the specified bytes  
            mdInst.update(btInput);  
            //get ciphertext  
            byte[] md = mdInst.digest();  
            //Convert ciphertext to hexadecimal string form  
            int j = md.length;  
            char str[] = new char[j * 2];  
            int k = 0;  
            for (int i = 0; i < j; i++) {  
                byte byte0 = md[i];  
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];  
                str[k++] = hexDigits[byte0 & 0xf];  
            }  
            return new String(str);  
        }  
        catch (Exception e) {  
            e.printStackTrace ();  
            return null;  
        }  
    }  
}

Called with the following two lines of code:

 

/************************************MD5 encryption test ********** ********************/
String srcString = "yanzi1225627";
System.out.println("MD5 encrypted = " + MD5Util.getMD5String(srcString));

2. RSA encryption

RSA is reversible, a string can be encrypted by rsa, and the encrypted string can be sent to the opposite end such as a server, and then decrypted. The premise is that the server knows the decrypted private key. Of course, this private key is best not to be transmitted over the network. The following variables are required in the RSA algorithm description:

1, p and q are not equal, two prime numbers large enough. p and q are confidential

2. n = p*qn is public

3、f(n) = (p-1)*(q-1)

4. e is a prime number that is relatively prime to f(n)

5. Calculate the parameter d 

6. After the above 5 steps, the public key KU=(e,n) and the private key KR=(d,n) are obtained

The following two articles describe this clearly:

http://wenku.baidu.com/view/e53fbe36a32d7375a417801b.html

http://bank.hexun.com/2009-06-24/118958531.html

The following is the java implementation of the RSAUtil.java class:

package org.rsa.util;  
  
import javax.crypto.Cipher;  
import java.security.*;  
import java.security.spec.RSAPublicKeySpec;  
import java.security.spec.RSAPrivateKeySpec;  
import java.security.spec.InvalidKeySpecException;  
import java.security.interfaces.RSAPrivateKey;  
import java.security.interfaces.RSAPublicKey;  
import java.io. *;  
import java.math.BigInteger;  
  
/**
 * RSA tool class. Provides encryption, decryption, key generation, etc. methods.
 * You need to download bcprov-jdk14-123.jar from http://www.bouncycastle.org.
 * RSA encryption principle overview   
 * The security of RSA relies on the decomposition of large numbers, and both the public and private keys are functions of two large prime numbers (decimal digits greater than 100).   
 * It is assumed that inferring plaintext from a key and ciphertext is as difficult as factoring the product of two large prime numbers   
 * ===================================================================   
 * (The security of this algorithm has not been proved theoretically)   
 * ===================================================================   
 * Key generation:   
 * 1. Select two large prime numbers p,q and calculate n=p*q;   
 * 2. Randomly select the encryption key e, requiring e and (p-1)*(q-1) to be relatively prime   
 * 3. Use the Euclid algorithm to calculate the decryption key d so that it satisfies e*d = 1(mod(p-1)*(q-1)) (where n, d are also coprime)   
 * 4: So far, the public key is (n, e) and the private key is (n, d)   
 * ===================================================================   
 * Encryption and decryption method:   
 * 1. First divide the information m (binary representation) to be encrypted into equal-length data blocks m1,m2,...,mi block length s (as large as possible), where 2^s<n   
 * 2: The corresponding ciphertext is: ci = mi^e(mod n)   
 * 3: Calculate as follows when decrypting: mi = ci^d(mod n)   
 * ===================================================================   
 * RSA speed   
 * Due to the large number of calculations, the fastest case of RSA is 100 times slower than DES, whether it is implemented in software or hardware.   
 * Speed ​​has always been a drawback of RSA. Generally only used for small amount of data encryption.  
 *File name: RSAUtil.java<br>
 *@author Dong Liwei<br>
 *Version:<br>
 *Description: <br>
 *Creation time: 2008-9-23 09:58:16 pm<br>
 *File description: <br>
 *Modified by: <br>
 *Modified date: <br>
 *Modify description: <br>
 */  
public class RSAUtil {  
  
    // key pair  
    private KeyPair keyPair = null;  
      
    /**
     * Initialize key pair
     */  
    public RSAUtil(){  
        try {  
            this.keyPair = this.generateKeyPair();  
        } catch (Exception e) {  
            e.printStackTrace ();  
        }  
    }  
      
    /**
    * Generate key pair
    * @return KeyPair
    * @throws Exception
    */  
    private KeyPair generateKeyPair() throws Exception {  
        try {  
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());  
            //This value is related to the size of the block encryption and can be changed, but it should not be too large, otherwise the efficiency will be low  
            final int KEY_SIZE = 1024;  
            keyPairGen.initialize(KEY_SIZE, new SecureRandom());  
            KeyPair keyPair = keyPairGen.genKeyPair();  
            return keyPair;  
        } catch (Exception e) {  
            throw new Exception(e.getMessage());  
        }  
      
    }  
  
    /**
    * Generate public key
    * @param modulus
    * @param publicExponent
    * @return RSAPublicKey
    * @throws Exception
    */  
    private RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent) throws Exception {  
      
        KeyFactory keyFac = null;  
        try {  
            keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());  
        } catch (NoSuchAlgorithmException ex) {  
        throw new Exception(ex.getMessage());  
        }  
        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));  
        try {  
            return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);  
        } catch (InvalidKeySpecException ex) {  
            throw new Exception(ex.getMessage());  
        }  
      
    }  
  
    /**
    * Generate private key
    * @param modulus
    * @param privateExponent
    * @return RSAPrivateKey
    * @throws Exception
    */  
    private RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) throws Exception {  
        KeyFactory keyFac = null;  
        try {  
            keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());  
        } catch (NoSuchAlgorithmException ex) {  
            throw new Exception(ex.getMessage());  
        }  
        RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));  
        try {  
            return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);  
        } catch (InvalidKeySpecException ex) {  
            throw new Exception(ex.getMessage());  
        }  
    }  
  
    /**
    * Encrypted
    * @param key encrypted key
    * @param data plaintext data to be encrypted
    * @return encrypted data
    * @throws Exception
    */  
    public byte[] encrypt(Key key, byte[] data) throws Exception {  
        try {  
            Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());  
            cipher.init(Cipher.ENCRYPT_MODE, key);  
            //Get the encrypted block size, such as: the data before encryption is 128 bytes, and key_size=1024, the encrypted block size is 127 bytes, and the encrypted block size is 128 bytes;  
            //So there are 2 encrypted blocks, the first is 127 bytes and the second is 1 byte  
            int blockSize = cipher.getBlockSize();  
            int outputSize = cipher.getOutputSize(data.length);//Get the encrypted block size after encryption  
            int leavedSize = data.length % blockSize;  
            int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;  
            byte[] raw = new byte[outputSize * blocksSize];  
            int i = 0;  
            while (data.length - i * blockSize > 0) {  
                if (data.length - i * blockSize > blockSize)  
                cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);  
                else  
                cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);  
                //The doUpdate method is not available here. After viewing the source code, I found that there is no actual action after each doUpdate except putting byte[] into ByteArrayOutputStream  
                //, and at the end of doFinal, all byte[] are encrypted, but at this time, the encrypted block size is likely to exceed OutputSize, so the dofinal method has to be used.  
                i++;  
            }  
            return raw;  
        } catch (Exception e) {  
        throw new Exception(e.getMessage());  
        }  
    }  
  
    /**
    * decrypt
    * @param key decrypted key
    * @param raw encrypted data
    * @return decrypted plaintext
    * @throws Exception
    */  
    public byte[] decrypt(Key key, byte[] raw) throws Exception {  
        try {  
            Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());  
            cipher.init(cipher.DECRYPT_MODE, key);  
            int blockSize = cipher.getBlockSize();  
            ByteArrayOutputStream bout = new ByteArrayOutputStream(64);  
            int j = 0;  
            while (raw.length - j * blockSize > 0) {  
                bout.write(cipher.doFinal(raw, j * blockSize, blockSize));  
                j++;  
            }  
            return bout.toByteArray();  
        } catch (Exception e) {  
            throw new Exception(e.getMessage());  
        }  
    }  
      
    /**
     * return public key
     * @return
     * @throws Exception  
     */  
    public RSAPublicKey getRSAPublicKey() throws Exception{  
          
        //get the public key  
        RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();  
        //Get the public key coefficient (byte array form)  
        byte[] pubModBytes = pubKey.getModulus().toByteArray();  
        //Return the public exponent of the public key (in the form of a byte array)  
        byte[] pubPubExpBytes = pubKey.getPublicExponent().toByteArray();  
        //generate public key  
        RSAPublicKey recoveryPubKey = this.generateRSAPublicKey(pubModBytes,pubPubExpBytes);  
        return recoveryPubKey;  
    }  
      
    /**
     * Get the private key
     * @return
     * @throws Exception  
     */  
    public RSAPrivateKey getRSAPrivateKey() throws Exception{  
          
        //Get the private key  
        RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();  
        //Return the private key coefficient (in the form of a byte array)  
        byte [] priModBytes = priKey.getModulus (). toByteArray ();  
        //Return the private key private exponent (in the form of a byte array)  
        byte[] priPriExpBytes = priKey.getPrivateExponent().toByteArray();  
        //generate private key  
        RSAPrivateKey recoveryPriKey = this.generateRSAPrivateKey(priModBytes,priPriExpBytes);  
        return recoveryPriKey;  
    }  
      
      
  
}  

 Test code:

 

/****************************RSA加密解密测试********************************/
try {
RSAUtil rsa = new RSAUtil();
String str = "yanzi1225627";
RSAPublicKey pubKey = rsa.getRSAPublicKey();
RSAPrivateKey priKey = rsa.getRSAPrivateKey();
byte[] enRsaBytes = rsa.encrypt(pubKey,str.getBytes());
String enRsaStr = new String(enRsaBytes, "UTF-8");
System.out.println("加密后==" + enRsaStr);
System.out.println("解密后==" + new String(rsa.decrypt(priKey, rsa.encrypt(pubKey,str.getBytes()))));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Here is the execution result:

 

After encryption==s?ko?1@lo????BJ?iE???1Ux?Kx&??=??n
O??l?>?????2r?y??8v-\A ??`????r?t3?-3y?hjL?M??Se?Z???????~?"??e??XZ? clover?
After decryption==yanzi1225627

The above code needs to use a package rsa.jar. I have packaged the download link and the above test code. The download link is as follows:

http://download.csdn.net/detail/yanzi1225627/7382263 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326865832&siteId=291194637