本文主要对消息摘要算法和加密算法做了整理,包括MD5、SHA、DES、AES、RSA等,并且提供了相应算法的Java实现和测试。
消息摘要算法最常用的场景就是数字签名以及数据(密码)加密了。(一般平时做项目用的比较多的就是使用MD5对用户密码进行加密)
数字签名主要用到了非对称密钥加密技术与数字摘要技术。数字签名技术是将摘要信息用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用HASH函数对收到的原文产生一个摘要信息,与解密的摘要信息对比。 如果相同,则说明收到的信息是完整的,在传输过程中没有被修改,否则说明信息被修改过.
因此数字签名能够验证信息的完整性。 数字签名是个加密的过程,数字签名验证是个解密的过程。
MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式 (也就是把一个任意长度的字节串变换成一定长的十六进制数字串)。
利用JDK提供java.security.MessageDigest类实现MD5算法:
package com.snailclimb.ks.securityAlgorithm;import java.security.MessageDigest;public class MD5Demo {// testpublic static void main(String[] args) {System.out.println(getMD5Code("你若安好,便是晴天"));}private MD5Demo() {}// md5加密public static String getMD5Code(String message) {String md5Str = "";try {//创建MD5算法消息摘要MessageDigest md = Instance("MD5");//生成的哈希值的字节数组byte[] md5Bytes = md.Bytes());md5Str = bytes2Hex(md5Bytes);}catch(Exception e) {e.printStackTrace();}return md5Str;}// 2进制转16进制public static String bytes2Hex(byte[] bytes) {StringBuffer result = new StringBuffer();int temp;try {for (int i = 0; i < bytes.length; i++) {temp = bytes[i];if(temp < 0) {temp += 256;}if (temp < 16) {result.append("0");}result.HexString(temp));}} catch (Exception e) {e.printStackTrace();}String();}
}
结果:
6bab82679914f7cb480a120b532ffa80
注意MessageDigest类的几个方法:
static MessageDigest getInstance(String algorithm)//返回实现指定摘要算法的MessageDigest对象
byte[] digest(byte[] input)//使用指定的字节数组对摘要执行最终更新,然后完成摘要计算。
package com.snailclimb.ks.securityAlgorithm;public class MD5{/**四个链接变量*/private final int A=0x67452301;private final int B=0xefcdab89;private final int C=0x98badcfe;private final int D=0x10325476;/**ABCD的临时变量*/private int Atemp,Btemp,Ctemp,Dtemp;/**常量ti*公式:floor(abs(sin(i+1))×(2pow32)*/private final int K[]={0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391};/**向左位移数,计算方法未知*/private final int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21};/**初始化函数*/private void init(){Atemp=A;Btemp=B;Ctemp=C;Dtemp=D;}/**移动一定位数*/private int shift(int a,int s){return(a<<s)|(a>>>(32-s));//右移的时候,高位一定要补零,而不是补充符号位}/**主循环*/private void MainLoop(int M[]){int F,g;int a=Atemp;int b=Btemp;int c=Ctemp;int d=Dtemp;for(int i = 0; i < 64; i ++){if(i<16){F=(b&c)|((~b)&d);g=i;}else if(i<32){F=(d&b)|((~d)&c);g=(5*i+1)%16;}else if(i<48){F=b^c^d;g=(3*i+5)%16;}else{F=c^(b|(~d));g=(7*i)%16;}int tmp=d;d=c;c=b;b=b+shift(a+F+K[i]+M[g],s[i]);a=tmp;}Atemp=a+Atemp;Btemp=b+Btemp;Ctemp=c+Ctemp;Dtemp=d+Dtemp;}/**填充函数*处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)*填充方式为先加一个0,其它位补零*最后加上64位的原来长度*/private int[] add(String str){int num=((str.length()+8)/64)+1;//以512位,64个字节为一组int strByte[]=new int[num*16];//64/4=16,所以有16个整数for(int i=0;i<num*16;i++){//全部初始化0strByte[i]=0;}int i;for(i=0;i<str.length();i++){strByte[i>>2]|=str.charAt(i)<<((i%4)*8);//一个整数存储四个字节,小端序}strByte[i>>2]|=0x80<<((i%4)*8);//尾部添加1/**添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位*/strByte[num*16-2]=str.length()*8;return strByte;}/**调用函数*/public String getMD5(String source){init();int strByte[]=add(source);for(int i=0;i<strByte.length/16;i++){int num[]=new int[16];for(int j=0;j<16;j++){num[j]=strByte[i*16+j];}MainLoop(num);}return changeHex(Atemp)+changeHex(Btemp)+changeHex(Ctemp)+changeHex(Dtemp);}/**整数变成16进制字符串*/private String changeHex(int a){String str="";for(int i=0;i<4;i++){str+=String.format("%2s", HexString(((a>>i*8)%(1<<8))&0xff)).replace(' ', '0');}return str;}/**单例*/private static MD5 instance;public static MD5 getInstance(){if(instance==null){instance=new MD5();}return instance;}private MD5(){};public static void main(String[] args){String strInstance().getMD5("你若安好,便是晴天");System.out.println(str);}
}
对于长度小于2^64位的消息,SHA1会产生一个160位(40个字符)的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。
SHA1有如下特性:
*利用JDK提供java.security.MessageDigest类实现SHA1算法:
package com.snailclimb.ks.securityAlgorithm;import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class SHA1Demo {public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println(getSha1("你若安好,便是晴天"));}public static String getSha1(String str) {if (null == str || 0 == str.length()) {return null;}char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };try {//创建SHA1算法消息摘要对象MessageDigest mdTemp = Instance("SHA1");//使用指定的字节数组更新摘要。mdTemp.Bytes("UTF-8"));//生成的哈希值的字节数组byte[] md = mdTemp.digest();//SHA1算法生成信息摘要关键过程int j = md.length;char[] buf = new char[j * 2];int k = 0;for (int i = 0; i < j; i++) {byte byte0 = md[i];buf[k++] = hexDigits[byte0 >>> 4 & 0xf];buf[k++] = hexDigits[byte0 & 0xf];}return new String(buf);} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}return "0";}
}
结果:
8ce764110a42da9b08504b20e26b19c9e3382414
密钥加密技术的密码体制分为对称密钥体制和非对称密钥体制两种。相应地,对数据加密的技术分为两类,即对称加密(私人密钥加密)和非对称加密(公开密钥加密)。
对称加密以数据加密标准(DES,Data Encryption Standard)算法为典型代表,非对称加密通常以RSA(Rivest Shamir Adleman)算法为代表。
对称加密的加密密钥和解密密钥相同。非对称加密的加密密钥和解密密钥不同,加密密钥可以公开而解密密钥需要保密
常被用在电子商务或者其他需要保证网络传输安全的范围。
加密密钥和解密密钥相同的加密算法。
对称加密算法使用起来简单快捷,密钥较短,且破译困难,除了数据加密标准(DES), 另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,而且对计算机功能要求也没有那么高。IDEA加密标准由PGP(Pretty Good Privacy)系统使用。
DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,现在已经过时。
DES算法实现 :
package com.snailclimb.ks.securityAlgorithm;import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
pto.spec.DESKeySpec;
pto.SecretKeyFactory;
pto.SecretKey;
pto.Cipher;/*** DES加密介绍 DES是一种对称加密算法,所谓对称加密算法即:加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究,* 后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,* 24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法,本文简单讲解DES的JAVA实现 。* 注意:DES加密和解密过程中,密钥长度都必须是8的倍数*/
public class DesDemo {public DesDemo() {}// 测试public static void main(String args[]) {// 待加密内容String str = "cryptology";// 密码,长度要是8的倍数String password = "95880288";byte[] result;try {result = Bytes(), password);System.out.println("加密后:" + result);byte[] decryResult = DesDemo.decrypt(result, password);System.out.println("解密后:" + new String(decryResult));} catch (UnsupportedEncodingException e2) {// TODO Auto-generated catch blocke2.printStackTrace();} catch (Exception e1) {e1.printStackTrace();}}// 直接将如上内容解密/*** 加密* * @param datasource* byte[]* @param password* String* @return byte[]*/public static byte[] encrypt(byte[] datasource, String password) {try {SecureRandom random = new SecureRandom();DESKeySpec desKey = new Bytes());// 创建一个密匙工厂,然后用它把DESKeySpec转换成SecretKeyFactory keyFactory = Instance("DES");SecretKey securekey = ateSecret(desKey);// Cipher对象实际完成加密操作Cipher cipher = Instance("DES");// 用密匙初始化Cipher对象,ENCRYPT_MODE用于将 Cipher 初始化为加密模式的常量cipher.init(Cipher.ENCRYPT_MODE, securekey, random);// 现在,获取数据并加密// 正式执行加密操作return cipher.doFinal(datasource); // 按单部分操作加密或解密数据,或者结束一个多部分操作} catch (Throwable e) {e.printStackTrace();}return null;}/*** 解密* * @param src* byte[]* @param password* String* @return byte[]* @throws Exception*/public static byte[] decrypt(byte[] src, String password) throws Exception {// DES算法要求有一个可信任的随机数源SecureRandom random = new SecureRandom();// 创建一个DESKeySpec对象DESKeySpec desKey = new Bytes());// 创建一个密匙工厂SecretKeyFactory keyFactory = Instance("DES");// 返回实现指定转换的// Cipher// 对象// 将DESKeySpec对象转换成SecretKey对象SecretKey securekey = ateSecret(desKey);// Cipher对象实际完成解密操作Cipher cipher = Instance("DES");// 用密匙初始化Cipher对象cipher.init(Cipher.DECRYPT_MODE, securekey, random);// 真正开始解密操作return cipher.doFinal(src);}
}
结果:
加密后:[B@50cbc42f
解密后:cryptology
IDEA算法实现
package com.snailclimb.ks.securityAlgorithm;import java.security.Key;
import java.security.Security;pto.Cipher;
pto.KeyGenerator;
pto.SecretKey;
pto.spec.SecretKeySpec;import dec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;public class IDEADemo {public static void main(String args[]) {bcIDEA();}public static void bcIDEA() {String src = blog security idea";try {Security.addProvider(new BouncyCastleProvider());//生成keyKeyGenerator keyGenerator = Instance("IDEA");keyGenerator.init(128);SecretKey secretKey = ateKey();byte[] keyBytes = Encoded();//转换密钥Key key = new SecretKeySpec(keyBytes, "IDEA");//加密Cipher cipher = Instance("IDEA/ECB/ISO10126Padding");cipher.init(Cipher.ENCRYPT_MODE, key);byte[] result = cipher.Bytes());System.out.println("bc idea encrypt : " + deBase64String(result));//解密cipher.init(Cipher.DECRYPT_MODE, key);result = cipher.doFinal(result);System.out.println("bc idea decrypt : " + new String(result));} catch (Exception e) {e.printStackTrace();}}
}
RSA是目前最有影响力和最常用的公钥加密算法。它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
RAS算法实现:
package com.snailclimb.ks.securityAlgorithm;import dec.binary.Base64;import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;pto.Cipher;/*** Created by humf.需要依赖 commons-codec 包*/
public class RSADemo {public static void main(String[] args) throws Exception {Map<String, Key> keyMap = initKey();String publicKey = getPublicKey(keyMap);String privateKey = getPrivateKey(keyMap);System.out.println(keyMap);System.out.println("-----------------------------------");System.out.println(publicKey);System.out.println("-----------------------------------");System.out.println(privateKey);System.out.println("-----------------------------------");byte[] encryptByPrivateKey = encryptByPrivateKey("123456".getBytes(), privateKey);byte[] encryptByPublicKey = encryptByPublicKey("123456", publicKey);System.out.println(encryptByPrivateKey);System.out.println("-----------------------------------");System.out.println(encryptByPublicKey);System.out.println("-----------------------------------");String sign = sign(encryptByPrivateKey, privateKey);System.out.println(sign);System.out.println("-----------------------------------");boolean verify = verify(encryptByPrivateKey, publicKey, sign);System.out.println(verify);System.out.println("-----------------------------------");byte[] decryptByPublicKey = decryptByPublicKey(encryptByPrivateKey, publicKey);byte[] decryptByPrivateKey = decryptByPrivateKey(encryptByPublicKey, privateKey);System.out.println(decryptByPublicKey);System.out.println("-----------------------------------");System.out.println(decryptByPrivateKey);}public static final String KEY_ALGORITHM = "RSA";public static final String SIGNATURE_ALGORITHM = "MD5withRSA";private static final String PUBLIC_KEY = "RSAPublicKey";private static final String PRIVATE_KEY = "RSAPrivateKey";public static byte[] decryptBASE64(String key) {return Base64.decodeBase64(key);}public static String encryptBASE64(byte[] bytes) {deBase64String(bytes);}/*** 用私钥对信息生成数字签名** @param data* 加密数据* @param privateKey* 私钥* @return* @throws Exception*/public static String sign(byte[] data, String privateKey) throws Exception {// 解密由base64编码的私钥byte[] keyBytes = decryptBASE64(privateKey);// 构造PKCS8EncodedKeySpec对象PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory = Instance(KEY_ALGORITHM);// 取私钥匙对象PrivateKey priKey = atePrivate(pkcs8KeySpec);// 用私钥对信息生成数字签名Signature signature = Instance(SIGNATURE_ALGORITHM);signature.initSign(priKey);signature.update(data);return encryptBASE64(signature.sign());}/*** 校验数字签名** @param data* 加密数据* @param publicKey* 公钥* @param sign* 数字签名* @return 校验成功返回true 失败返回false* @throws Exception*/public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {// 解密由base64编码的公钥byte[] keyBytes = decryptBASE64(publicKey);// 构造X509EncodedKeySpec对象X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法KeyFactory keyFactory = Instance(KEY_ALGORITHM);// 取公钥匙对象PublicKey pubKey = atePublic(keySpec);Signature signature = Instance(SIGNATURE_ALGORITHM);signature.initVerify(pubKey);signature.update(data);// 验证签名是否正常return signature.verify(decryptBASE64(sign));}public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {// 对密钥解密byte[] keyBytes = decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = Instance(KEY_ALGORITHM);Key privateKey = atePrivate(pkcs8KeySpec);// 对数据解密Cipher cipher = Algorithm());cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 解密<br>* 用私钥解密** @param data* @param key* @return* @throws Exception*/public static byte[] decryptByPrivateKey(String data, String key) throws Exception {return decryptByPrivateKey(decryptBASE64(data), key);}/*** 解密<br>* 用公钥解密** @param data* @param key* @return* @throws Exception*/public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception {// 对密钥解密byte[] keyBytes = decryptBASE64(key);// 取得公钥X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = Instance(KEY_ALGORITHM);Key publicKey = atePublic(x509KeySpec);// 对数据解密Cipher cipher = Algorithm());cipher.init(Cipher.DECRYPT_MODE, publicKey);return cipher.doFinal(data);}/*** 加密<br>* 用公钥加密** @param data* @param key* @return* @throws Exception*/public static byte[] encryptByPublicKey(String data, String key) throws Exception {// 对公钥解密byte[] keyBytes = decryptBASE64(key);// 取得公钥X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = Instance(KEY_ALGORITHM);Key publicKey = atePublic(x509KeySpec);// 对数据加密Cipher cipher = Algorithm());cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.Bytes());}/*** 加密<br>* 用私钥加密** @param data* @param key* @return* @throws Exception*/public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {// 对密钥解密byte[] keyBytes = decryptBASE64(key);// 取得私钥PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = Instance(KEY_ALGORITHM);Key privateKey = atePrivate(pkcs8KeySpec);// 对数据加密Cipher cipher = Algorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);return cipher.doFinal(data);}/*** 取得私钥** @param keyMap* @return* @throws Exception*/public static String getPrivateKey(Map<String, Key> keyMap) throws Exception {Key key = (Key) (PRIVATE_KEY);return Encoded());}/*** 取得公钥** @param keyMap* @return* @throws Exception*/public static String getPublicKey(Map<String, Key> keyMap) throws Exception {Key key = (PUBLIC_KEY);return Encoded());}/*** 初始化密钥** @return* @throws Exception*/public static Map<String, Key> initKey() throws Exception {KeyPairGenerator keyPairGen = Instance(KEY_ALGORITHM);keyPairGen.initialize(1024);KeyPair keyPair = ateKeyPair();Map<String, Key> keyMap = new HashMap(2);keyMap.put(PUBLIC_KEY, Public());// 公钥keyMap.put(PRIVATE_KEY, Private());// 私钥return keyMap;}}
结果:
{RSAPublicKey=Sun RSA public key, 1024 bitsmodulus: 115328826086047873902606456571034976538836553998745367981848911677968062571831626674499650854318207280419960767020601253071739555161388135589487284843845439403614883967713749605268831336418001722701924537624573180276356615050309809260289965219855862692230362893996010057188170525719351126759886050891484226169public exponent: 65537, RSAPrivateKey=sun.security.rsa.RSAPrivateCrtKeyImpl@93479}
-----------------------------------
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkO9PBTOFJQTkzznALN62PU7ixd9YFjXrt2dPOGj3wwhymbOU8HLoCztjwpLXHgbpBUJlGmbURV955M1BkZ1kr5dkZYR5x1gO4xOnu8rEipy4AAMcpFttfiarIZrtzL9pKEvEOxABltVN4yzFDr3IjBqY46aHna7YjwhXI0xHieQIDAQAB
-----------------------------------
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKQ708FM4UlBOTPOcAs3rY9TuLF31gWNeu3Z084aPfDCHKZs5TwcugLO2PCktceBukFQmUaZtRFX3nkzUGRnWSvl2RlhHnHWA7jE6e7ysSKnLgAAxykW21+Jqshmu3Mv2koS8Q7EAGW1U3jLMUOvciMGpjjpoedrtiPCFcjTEeJ5AgMBAAECgYAK4sxOa8IjEOexv2U92Rrv/SSo3sCY7Z/QVDft2V9xrewoO9+V9HF/7iYDDWffKYInAiimvVl7JM/iSLxza0ZFv29VMpyDcr4TigYmWwBlk7ZbxSTkqLdNwxxldMmEoTn1py53MUm+1V1K3rzNvJjuZaZFAevU7vUnwQwD+JGQYQJBAM9HBaC+dF3PJ2mkXekHpDS1ZPaSFdrdzd/GvHFi/cJAMM+Uz6PmpkosNXRtOpSYWwlOMRamLZtrHhfQoqSk3S8CQQDK1qL1jGvVdqw5OjqxktR7MmOsWUVZdWiBN+6ojxBgA0yVn0n7vkdAAgEZBj89WG0VHPEu3hd4AgXFZHDfXeDXAkBvSn7nE9t/Et7ihfI2UHgGJO8UxNMfNMB5Skebyb7eMYEDs67ZHdpjMOFypcMyTatzj5wjwQ3zyMvblZX+ONbZAkAX4ysRy9WvL+icXLUo0Gfhkk+WrnSyUldaUGH0y9Rb2kecn0OxN/lgGlxSvB+ac910zRHCOTl+Uo6nbmq0g3PFAkAyqA4eT7G9GXfncakgW1Kdkn72w/ODpozgfhTLNX0SGw1ITML3c4THTtH5h3zLi3AF9zJO2O+K6ajRbV0szHHI
-----------------------------------
[B@387c703b
-----------------------------------
[B@224aed64
-----------------------------------
la4Hc4n/UbeBu0z9iLRuwKVv014SiOJMXkO5qdJvKBsw0MlnsrM+89a3p73yMrb1dAnCU/2kgO0PtFpvmG8pzxTe1u/5nX/25iIyUXALlwVRptJyjzFE83g2IX0XEv/Dxqr1RCRcrMHOLQM0oBoxZCaChmyw1Ub4wsSs6Ndxb9M=
-----------------------------------
true
-----------------------------------
[B@c39f790
-----------------------------------
[B@71e7a66b
本文发布于:2024-02-02 11:11:56,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170684351743407.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |