各类加密算法-Java版

在APP的网络协议中,这些对称加密和非对称加密算法常会用在APP和服务器的交互数据中request和response(部分可能会用在数据的签名),识别这些算法是非常重要的,这里给出整理好的Java版(smali层)加密算法,C/C++(so层)也类似,主要就是识别这两行

Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv)

Java版AES算法

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/*******************************************************************************
 * AES加解密算法
 * http://tools.lami.la/jiami/aes
 * 说明:AES数据块长度为128位,所以IV长度需要为16个字符(ECB模式不用IV),密钥根据指定密钥位数分别为16、24、32个字符,IV与密钥超过长度则截取,不足则在末尾填充'\0'补足
 *******************************************************************************/


public class AES {

    // 加密
    public static String Encrypt(String Src, String Key) throws Exception {
        if (Key == null) {
            System.out.print("Key为空null");
            return null;
        }
        // 判断Key是否为16位
        if (Key.length() != 16) {
            System.out.print("Key长度不是16位");
            return null;
        }
        byte[] key = Key.getBytes();
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/补码方式"
        
        String IV="20150116";
        StringBuffer buffer = new StringBuffer(16);  
        buffer.append(IV);
        while (buffer.length() < 16) {  //IV不足则在末尾填充'\0'补足
        	buffer.append("\0");  
        }  
        if (buffer.length() > 16)  {    //IV超过长度则截取 
            buffer.setLength(16);  
        } 
    
        IvParameterSpec iv = new IvParameterSpec(buffer.toString().getBytes());//使用CBC模式,需要一个向量iv,可增加加密算法的强度
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
        byte[] encrypted = cipher.doFinal(Src.getBytes());
        /*原始加密数据
          for (int i = 0; i < encrypted.length; i ++) {
              System.out.printf("0x%02X ", encrypted[i]);               
        }*/
        return new BASE64Encoder().encode(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。
    }

    // AES/CBC/PKCS5Padding 解密  
    public static String Decrypt(String Src, String Key) throws Exception {
        try {
            // 判断Key是否正确
            if (Key == null) {
                System.out.print("Key为空null");
                return null;
            }
            // 判断Key是否为16位
            if (Key.length() != 16) {
                System.out.print("Key长度不是16位");
                return null;
            }
            byte[] key = Key.getBytes("ASCII");
            SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            
            String IV="20150116";
            StringBuffer buffer = new StringBuffer(16);  
            buffer.append(IV);
            while (buffer.length() < 16) {  
                buffer.append("\0");  
            }  
            if (buffer.length() > 16) {  
                buffer.setLength(16);  
            } 
            
            IvParameterSpec iv = new IvParameterSpec(buffer.toString().getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(Src);//先用base64解密
            try {
                byte[] original = cipher.doFinal(encrypted1);
                String originalString = new String(original);
                return originalString;
            } catch (Exception e) {
                System.out.println(e.toString());
                return null;
            }
        } catch (Exception ex) {
            System.out.println(ex.toString());
            return null;
        }
    }
    
    
   //AES/ECB/NoPadding 解密     
    public static String Decrypt2(byte[] Src, String Key) throws Exception { 
        try {
            // 判断Key是否正确
            if (Key == null) {
                System.out.print("Key为空null");
                return null;
            }
            // 判断Key是否为16位
            if (Key.length() != 16) {
                System.out.print("Key长度不是16位");
                return null;
            }
            byte[] key = Key.getBytes("ASCII");
            SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
            
            
           
            cipher.init(Cipher.DECRYPT_MODE, keySpec);
            byte[] encrypted1 = Src;
            try {
                byte[] original = cipher.doFinal(encrypted1);
                String originalString = new String(original);
                return originalString;
            } catch (Exception e) {
                System.out.println(e.toString());
                return null;
            }
        } catch (Exception ex) {
            System.out.println(ex.toString());
            return null;
        }
    }

    public static void main(String[] args) throws Exception {
        /*
         * 加密用的Key 可以用26个字母和数字组成,最好不要用保留字符,虽然不会错,至于怎么裁决,个人看情况而定
         * 此处使用AES-128-CBC加密模式,key需要为16位。
         */
        String Key = "DATA_KEY20150116";
        // 需要加密的字串
        String Src = "{\"data\":{\"page\":1,\"pageSize\":100},\"device\":\"android\",\"imei\":\"867514021468675\",\"mac\":\"\",\"token\":\"\",\"versionId\":\"4.2.9\"}";
        System.out.println(Src);
        // 加密
        String enString = AES.Encrypt(Src, Key);
        System.out.println("加密后的字串是:" + enString);

       
        // 解密
        String DeString = AES.Decrypt(enString, Key);
        System.out.println("解密后的字串是:" + DeString);
        
        //2018全国网络空间安全技术大赛 mobile3 解密
        byte[] cipher = new byte[]{(byte)0x46,(byte)0x00,(byte)0x94,(byte)0x74,(byte)0x1F,(byte)0xAB,(byte)0x14,(byte)0xF0,(byte)0xB2,(byte)0x59,(byte)0xA9,(byte)0x19,(byte)0xC0,(byte)0x43,(byte)0xDC,(byte)0xC3};
        Key="com.example.forc";
        String flag = AES.Decrypt2(cipher, Key);
        System.out.println("flag是:" + flag);
        
      
    }
}

Java版DES算法

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class DES{

	// The initialization vector(IV) should be 8 bytes  
    private final static byte[] EncryptionIV = new byte[]{18, 52, 86, 120, -112, -85, -51, -17};  //初始化向量
    private final static byte[] key = new byte[]{88,81,-114,39,-127,-23,64,0};
    
	public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException {
		String plainText ="{\"data\":{\"activityIds\":\"\",\"longitude\":116.356247,\"latitude\":39.964974},\"clientInfo\":\"23000,yingyongbao,1,44400\",\"token\":\"\",\"version\":1}";  
	      
	    DESKeySpec keySpec = new DESKeySpec(key);  
	    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
	    SecretKey secretKey = keyFactory.generateSecret(keySpec);  //密钥生成器产生真正的DES密钥 
	    IvParameterSpec iv = new IvParameterSpec(EncryptionIV);  
	    Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 
        
	    cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);  
	    byte[] cipherData = cipher.doFinal(plainText.getBytes());  
	    System.out.println("加密 :"+new BASE64Encoder().encode(cipherData));  
	      
	    cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);  
	    byte[] plainData = cipher.doFinal(cipherData);  
	    System.out.println("解密 :"+new String(plainData));
	    
	    byte[] ReturnData=new BASE64Decoder().decodeBuffer("Aw4bp9aZGPM2QzQYAoWdXjdVLBJZ1mc1rzmdypgsntqQ2nc4KZHfJn3FtcXYmCKRdmXMSKN1IS3s3p2fpUzM+JaW0uov4S4/CGgroLzK4KOtCnvG6kBM4IwfqEMiJtY6DFpLl8I70JZmfKzj8k6mATKu/4vohNQFQrviikJuiZtIbkQa7SAFTA==");
	    cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);  
	    byte[] ReturnData2 = cipher.doFinal(ReturnData);  
	    System.out.println("服务器的数据解密 :"+new String(ReturnData2));    		
    }
}

Java版RSA算法

import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;
import java.math.BigInteger;  
import java.security.spec.RSAPublicKeySpec;  
import java.net.URLEncoder;


/**
 * 1、公钥加密,私钥解密用于信息加密
 * 2、私钥加密,公钥解密用于数字签名
 */
public class RSA {
    /**
     * 测试方法
     * @throws InvalidKeySpecException 
     * @throws NoSuchAlgorithmException 
     */
    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException {

        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLNbmKl9/gLn7Bef/xtUkshC1WyrLZLRpXCcFYR1gQi0isWsZBTicC4efBOkkNG3r+1ue0gvtuU/tjREFGf4Y7HaKHGb5tNCOlMNeNjM5YLRwLFqrUSsQyD4rj4eua1ltearr24R0HilnTvnQm6Z/UY0s21vdOUFQBPY0GNAa+0wIDAQAB";
    	String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIs1uYqX3+AufsF5//G1SSyELVbKstktGlcJwVhHWBCLSKxaxkFOJwLh58E6SQ0bev7W57SC+25T+2NEQUZ/hjsdoocZvm00I6Uw142MzlgtHAsWqtRKxDIPiuPh65rWW15quvbhHQeKWdO+dCbpn9RjSzbW905QVAE9jQY0Br7TAgMBAAECgYBcYhbzpr5no/Nyqmf0G/6nkEAWbQYrogbs5AhvcUk8EXL1DnirNhYlj42hafC4xhflrvCtlo8NNKaLxewbwN1uuzG8A2jd+ROEXlx5HDh2ZluhtHzL/SmNcJXo684xAl2pCNVBjDcW48PcIBijke/sTVHTDsDCukLKDPUOM/mKIQJBAL96k4+jBscazsJiuZ6C3RFDVtRRDpf1dMgLgxcx63bAXkA2Arau0J49IAYmSVJoDXqDoJKWdXJVh9vHSkhN/48CQQC6Hk1/G0Y0nOylf6NOp0oMgc0A+etnwxHKqwtctPKjEYcJx2fzALzTtCoySLYXX7gLnPIQXpQBTUysG5skBKp9AkEAiSQm6fqu0Q4fRlRlc+VwpnufhgPkOuw/z0OHiaZkajJPjxfgC63bl2paNG1ZmJ8UAEqkSDlhNxmRa9UqG+1ZewJASaQxz6gwCCNLM1SkfjuM/hPh1JAOh9jUUleJQF5MXx9RSho/VBQnorB3vbutaOQzw0yPLtDtSPKX8sVdhkveVQJAIDsJP5X8Tey6zXTUISor7PF0TSiKdE4k0IwKoy9y8HmQ+AU8+xyr/iOt5lvaGxKlBK8N/7yCw5H4qHnJaHT+Bg==";
        
        String str = "RSA_By_Java!";
        // 公钥加密,私钥解密
        String enStr1 = RSA.encryptByPublic(str, publicKey);
        System.out.println("公钥加密后:"+enStr1);
        String deStr1 = RSA.decryptByPrivate(enStr1, privateKey);
        System.out.println("私钥解密后:"+deStr1);
        // 私钥加密,公钥解密
        String enStr2 = RSA.encryptByPrivate(str, privateKey);
        System.out.println("私钥加密后:"+enStr2);
        String deStr2 = RSA.decryptByPublic(enStr2, publicKey);
        System.out.println("公钥解密后:"+deStr2);
        // 产生签名  
        String sign = sign(enStr2, privateKey);
        System.out.println("签名:"+sign);
        // 验证签名 
        boolean status = verify(enStr2, publicKey, sign);
        System.out.println("状态:"+status);
       
        
        
        System.out.println("以下为兆金所RSA协议分析");
        /*兆金所RSA协议分析
                        原始密钥:OpenSSLRSAPublicKey{modulus=98eaa55cb48cd4e860d41a9568758dcb563166a8e8ef77f1c03023f31d878599447df85c3fbb9279f886fff58936643939957a88187511f149ff710e57e74ca61867b4b3d1dae2da6b0805a8f0ed03eadfac3c508320c47ae472b68ffabf574f39bfd1b75d4499266c5c2d1193923fe793fd40b51cb34ce216e2b8f8ad1e8937,
    	publicExponent=10001}*/
        String publicModulus = "98eaa55cb48cd4e860d41a9568758dcb563166a8e8ef77f1c03023f31d878599447df85c3fbb9279f886fff58936643939957a88187511f149ff710e57e74ca61867b4b3d1dae2da6b0805a8f0ed03eadfac3c508320c47ae472b68ffabf574f39bfd1b75d4499266c5c2d1193923fe793fd40b51cb34ce216e2b8f8ad1e8937";
        try {
        	BigInteger keyInt = new BigInteger(publicModulus, 16);
        	BigInteger exponentInt = new BigInteger("10001", 16);
        	RSAPublicKeySpec keySpeck = new RSAPublicKeySpec(keyInt, exponentInt);
        	KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        	PublicKey PublicKey = keyFactory.generatePublic(keySpeck);
        	System.out.println(PublicKey);  
        	
        	// 返回加密后由Base64编码的加密信息
        	byte[] data ="{\"Page\":\"1\",\"pageSize\":\"5\"}".getBytes("UTF-8");
        	Cipher v0 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        	v0.init(1, ((Key)PublicKey));
        	byte[]  v2 = v0.doFinal(data);
        	System.out.println(encryptBase64(v2));
        	String Signature = URLEncoder.encode(encryptBase64(v2), "utf-8");   //URL编码
        	System.out.println(Signature);
        }
        catch (Exception e) {
        	e.printStackTrace();
        	}

        
    }
   
    
    
    /**
     * 公钥加密
     * @param encryptingStr
     * @param publicKey
     * @return
     */
    public static String encryptByPublic(String encryptingStr, String publicKeyStr){
        try {
            // 将公钥由字符串转为UTF-8格式的字节数组
            byte[] publicKeyBytes = decryptBase64(publicKeyStr);
            // 获得公钥  
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
            // 取得待加密数据
            byte[] data = encryptingStr.getBytes("UTF-8");
            KeyFactory factory;
            factory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 对数据加密  
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 返回加密后由Base64编码的加密信息
            return encryptBase64(cipher.doFinal(data));
        } catch (Exception e) {
            e.printStackTrace();
        }     
        return null;
    }
   
    
    /**
     * 私钥解密
     * @param encryptedStr
     * @param privateKey
     * @return
     */
    public static String decryptByPrivate(String encryptedStr, String privateKeyStr){
        try {
            // 对私钥解密  
            byte[] privateKeyBytes = decryptBase64(privateKeyStr);
            // 获得私钥 
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            // 获得待解密数据
            byte[] data = decryptBase64(encryptedStr);
            KeyFactory factory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = factory.generatePrivate(keySpec);
            // 对数据解密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // 返回UTF-8编码的解密信息
            return new String(cipher.doFinal(data), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }      
        return null;
    }

    /**
     * 私钥加密
     * @param encryptingStr
     * @param privateKey
     * @return
     */
    public static String encryptByPrivate(String encryptingStr, String privateKeyStr){
        try {
            byte[] privateKeyBytes = decryptBase64(privateKeyStr);
            // 获得私钥  
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes); 
            // 取得待加密数据
            byte[] data = encryptingStr.getBytes("UTF-8");
            KeyFactory factory = KeyFactory.getInstance("RSA");  
            PrivateKey privateKey = factory.generatePrivate(keySpec); 
            // 对数据加密 
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());  
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            // 返回加密后由Base64编码的加密信息
            return encryptBase64(cipher.doFinal(data));  
        } catch (Exception e) {
            e.printStackTrace();  
        }
        
        return null;
    }
    
    /**
     * 公钥解密
     * @param encryptedStr
     * @param privateKey
     * @return
     */
    public static String decryptByPublic(String encryptedStr, String publicKeyStr){
        try {
            // 对公钥解密  
            byte[] publicKeyBytes = decryptBase64(publicKeyStr);
            // 取得公钥  
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
            // 取得待加密数据
            byte[] data = decryptBase64(encryptedStr);
            KeyFactory factory = KeyFactory.getInstance("RSA");  
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 对数据解密  
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());  
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            // 返回UTF-8编码的解密信息
            return new String(cipher.doFinal(data), "UTF-8");  
        } catch (Exception e) {  
            e.printStackTrace();  
        }
        
        return null;
    }
    
    /**
     * 用私钥对加密数据进行签名
     * @param encryptedStr
     * @param privateKey
     * @return
     */
    public static String sign(String encryptedStr, String privateKey) {
        String str = "";  
        try {
            //将私钥加密数据字符串转换为字节数组
            byte[] data = encryptedStr.getBytes();
            // 解密由base64编码的私钥  
            byte[] bytes = decryptBase64(privateKey);  
            // 构造PKCS8EncodedKeySpec对象  
            PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(bytes);  
            // 指定的加密算法  
            KeyFactory factory = KeyFactory.getInstance("RSA");  
            // 取私钥对象  
            PrivateKey key = factory.generatePrivate(pkcs);  
            // 用私钥对信息生成数字签名  
            Signature signature = Signature.getInstance("SHA1withRSA");  
            signature.initSign(key);  
            signature.update(data);  
            str = encryptBase64(signature.sign());  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return str;  
    }
    
    /**
     * 校验数字签名 
     * @param encryptedStr
     * @param publicKey
     * @param sign
     * @return 校验成功返回true,失败返回false
     */
    public static boolean verify(String encryptedStr, String publicKey, String sign) {  
        boolean flag = false;
        try {
            //将私钥加密数据字符串转换为字节数组
            byte[] data = encryptedStr.getBytes();
            // 解密由base64编码的公钥  
            byte[] bytes = decryptBase64(publicKey);  
            // 构造X509EncodedKeySpec对象  
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);  
            // 指定的加密算法  
            KeyFactory factory = KeyFactory.getInstance("RSA");  
            // 取公钥对象  
            PublicKey key = factory.generatePublic(keySpec);  
            // 用公钥验证数字签名  
            Signature signature = Signature.getInstance("SHA1withRSA");  
            signature.initVerify(key);  
            signature.update(data);  
            flag = signature.verify(decryptBase64(sign));
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return flag;  
    }
    
    /** 
     * BASE64 解码 
     * @param key 需要Base64解码的字符串 
     * @return 字节数组 
     */  
    public static byte[] decryptBase64(String key) {
        return Base64.getDecoder().decode(key);
    }
  
    /** 
     * BASE64 编码 
     * @param key 需要Base64编码的字节数组 
     * @return 字符串 
     */  
    public static String encryptBase64(byte[] key) {
        return new String(Base64.getEncoder().encode(key));
    }
  
}