Java中常用的加密方法(JDK)

加密,是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容。大体上分为 双向加密单向加密,而双向加密又分为 对称加密非对称加密(有些资料将加密直接分为对称加密和非对称加密)。

双向加密大体意思就是明文加密后形成密文,可以通过算法还原成明文。而单向加密只是对信息进行了摘要计算,不能通过算法生成明文,单向加密从严格意思上说不能算是加密的一种,应该算是摘要算法吧。具体区分可以参考:
(本人解释不清呢 …… )
http://security.group.iteye.com/group/wiki/1710-one-way-encryption-algorithm
一、双向加密
(一)、对称加密

采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。
需要对加密和解密使用相同密钥的加密算法。由于其速度,对称性加密通常在消息发送方需要加密大量数据时使用。对称性加密也称为密钥加密。
所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密。密钥是控制加密及解密过程的指令。

算法是一组规则,规定如何进行加密和解密。因此对称式加密本身不是安全的。   
常用的对称加密有:DES、IDEA、RC2、RC4、SKIPJACK、RC5、AES算法等

对称加密一般java类中中定义成员
Java代码   收藏代码
  1. //KeyGenerator 提供对称密钥生成器的功能,支持各种算法  
  2. private KeyGenerator keygen;  
  3. //SecretKey 负责保存对称密钥  
  4. private SecretKey deskey;  
  5. //Cipher负责完成加密或解密工作  
  6. private Cipher c;  
  7. //该字节数组负责保存加密的结果  
  8. private byte[] cipherByte;  

在构造函数中初始化
Java代码   收藏代码
  1. Security.addProvider(new com.sun.crypto.provider.SunJCE());  
  2. //实例化支持DES算法的密钥生成器(算法名称命名需按规定,否则抛出异常)  
  3. keygen = KeyGenerator.getInstance("DES");//  
  4. //生成密钥  
  5. deskey = keygen.generateKey();  
  6. //生成Cipher对象,指定其支持的DES算法  
  7. c = Cipher.getInstance("DES");  


1. DES算法为密码体制中的对称密码体制,又被成为美国数据加密标准,是1972年美国IBM公司研制的对称密码体制加密算法。 明文按64位进行分组, 密钥长64位,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位, 使得每个密钥都有奇数个1)分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法。

Java代码   收藏代码
  1. import java.security.InvalidKeyException;  
  2. import java.security.NoSuchAlgorithmException;  
  3. import java.security.Security;  
  4.   
  5. import javax.crypto.BadPaddingException;  
  6. import javax.crypto.Cipher;  
  7. import javax.crypto.IllegalBlockSizeException;  
  8. import javax.crypto.KeyGenerator;  
  9. import javax.crypto.NoSuchPaddingException;  
  10. import javax.crypto.SecretKey;  
  11.   
  12. public class EncrypDES {  
  13.       
  14.     //KeyGenerator 提供对称密钥生成器的功能,支持各种算法  
  15.     private KeyGenerator keygen;  
  16.     //SecretKey 负责保存对称密钥  
  17.     private SecretKey deskey;  
  18.     //Cipher负责完成加密或解密工作  
  19.     private Cipher c;  
  20.     //该字节数组负责保存加密的结果  
  21.     private byte[] cipherByte;  
  22.       
  23.     public EncrypDES() throws NoSuchAlgorithmException, NoSuchPaddingException{  
  24.         Security.addProvider(new com.sun.crypto.provider.SunJCE());  
  25.         //实例化支持DES算法的密钥生成器(算法名称命名需按规定,否则抛出异常)  
  26.         keygen = KeyGenerator.getInstance("DES");  
  27.         //生成密钥  
  28.         deskey = keygen.generateKey();  
  29.         //生成Cipher对象,指定其支持的DES算法  
  30.         c = Cipher.getInstance("DES");  
  31.     }  
  32.       
  33.     /** 
  34.      * 对字符串加密 
  35.      *  
  36.      * @param str 
  37.      * @return 
  38.      * @throws InvalidKeyException 
  39.      * @throws IllegalBlockSizeException 
  40.      * @throws BadPaddingException 
  41.      */  
  42.     public byte[] Encrytor(String str) throws InvalidKeyException,  
  43.             IllegalBlockSizeException, BadPaddingException {  
  44.         // 根据密钥,对Cipher对象进行初始化,ENCRYPT_MODE表示加密模式  
  45.         c.init(Cipher.ENCRYPT_MODE, deskey);  
  46.         byte[] src = str.getBytes();  
  47.         // 加密,结果保存进cipherByte  
  48.         cipherByte = c.doFinal(src);  
  49.         return cipherByte;  
  50.     }  
  51.   
  52.     /** 
  53.      * 对字符串解密 
  54.      *  
  55.      * @param buff 
  56.      * @return 
  57.      * @throws InvalidKeyException 
  58.      * @throws IllegalBlockSizeException 
  59.      * @throws BadPaddingException 
  60.      */  
  61.     public byte[] Decryptor(byte[] buff) throws InvalidKeyException,  
  62.             IllegalBlockSizeException, BadPaddingException {  
  63.         // 根据密钥,对Cipher对象进行初始化,DECRYPT_MODE表示加密模式  
  64.         c.init(Cipher.DECRYPT_MODE, deskey);  
  65.         cipherByte = c.doFinal(buff);  
  66.         return cipherByte;  
  67.     }  
  68.   
  69.     /** 
  70.      * @param args 
  71.      * @throws NoSuchPaddingException  
  72.      * @throws NoSuchAlgorithmException  
  73.      * @throws BadPaddingException  
  74.      * @throws IllegalBlockSizeException  
  75.      * @throws InvalidKeyException  
  76.      */  
  77.     public static void main(String[] args) throws Exception {  
  78.         EncrypDES de1 = new EncrypDES();  
  79.         String msg ="郭XX-搞笑相声全集";  
  80.         byte[] encontent = de1.Encrytor(msg);  
  81.         byte[] decontent = de1.Decryptor(encontent);  
  82.         System.out.println("明文是:" + msg);  
  83.         System.out.println("加密后:" + new String(encontent));  
  84.         System.out.println("解密后:" + new String(decontent));  
  85.     }  
  86.   
  87. }  


2. 3DES又称Triple DES,是DES加密算法的一种模式,它使用3条56位的密钥对3DES
数据进行三次加密。数据加密标准(DES)是美国的一种由来已久的加密标准,它使用对称密钥加密法,并于1981年被ANSI组织规范为ANSI X.3.92。DES使用56位密钥和密码块的方法,而在密码块的方法中,文本被分成64位大小的文本块然后再进行加密。比起最初的DES,3DES更为安全。   
3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),是DES的一个更安全的变形。它以DES为基本模块,通过组合分组方法设计出分组加密算法,其具体实现如下:
设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,P代表明文,C代表密文,
这样,   
3DES加密过程为:C=Ek3(Dk2(Ek1(P)))
3DES解密过程为:P=Dk1((EK2(Dk3(C)))
Java代码   收藏代码
  1. import java.security.InvalidKeyException;  
  2. import java.security.NoSuchAlgorithmException;  
  3. import java.security.Security;  
  4.   
  5. import javax.crypto.BadPaddingException;  
  6. import javax.crypto.Cipher;  
  7. import javax.crypto.IllegalBlockSizeException;  
  8. import javax.crypto.KeyGenerator;  
  9. import javax.crypto.NoSuchPaddingException;  
  10. import javax.crypto.SecretKey;  
  11.   
  12. public class EncrypDES3 {  
  13.   
  14.     // KeyGenerator 提供对称密钥生成器的功能,支持各种算法  
  15.     private KeyGenerator keygen;  
  16.     // SecretKey 负责保存对称密钥  
  17.     private SecretKey deskey;  
  18.     // Cipher负责完成加密或解密工作  
  19.     private Cipher c;  
  20.     // 该字节数组负责保存加密的结果  
  21.     private byte[] cipherByte;  
  22.   
  23.     public EncrypDES3() throws NoSuchAlgorithmException, NoSuchPaddingException {  
  24.         Security.addProvider(new com.sun.crypto.provider.SunJCE());  
  25.         // 实例化支持DES算法的密钥生成器(算法名称命名需按规定,否则抛出异常)  
  26.         keygen = KeyGenerator.getInstance("DESede");  
  27.         // 生成密钥  
  28.         deskey = keygen.generateKey();  
  29.         // 生成Cipher对象,指定其支持的DES算法  
  30.         c = Cipher.getInstance("DESede");  
  31.     }  
  32.   
  33.     /** 
  34.      * 对字符串加密 
  35.      *  
  36.      * @param str 
  37.      * @return 
  38.      * @throws InvalidKeyException 
  39.      * @throws IllegalBlockSizeException 
  40.      * @throws BadPaddingException 
  41.      */  
  42.     public byte[] Encrytor(String str) throws InvalidKeyException,  
  43.             IllegalBlockSizeException, BadPaddingException {  
  44.         // 根据密钥,对Cipher对象进行初始化,ENCRYPT_MODE表示加密模式  
  45.         c.init(Cipher.ENCRYPT_MODE, deskey);  
  46.         byte[] src = str.getBytes();  
  47.         // 加密,结果保存进cipherByte  
  48.         cipherByte = c.doFinal(src);  
  49.         return cipherByte;  
  50.     }  
  51.   
  52.     /** 
  53.      * 对字符串解密 
  54.      *  
  55.      * @param buff 
  56.      * @return 
  57.      * @throws InvalidKeyException 
  58.      * @throws IllegalBlockSizeException 
  59.      * @throws BadPaddingException 
  60.      */  
  61.     public byte[] Decryptor(byte[] buff) throws InvalidKeyException,  
  62.             IllegalBlockSizeException, BadPaddingException {  
  63.         // 根据密钥,对Cipher对象进行初始化,DECRYPT_MODE表示加密模式  
  64.         c.init(Cipher.DECRYPT_MODE, deskey);  
  65.         cipherByte = c.doFinal(buff);  
  66.         return cipherByte;  
  67.     }  
  68.   
  69.     /** 
  70.      * @param args 
  71.      * @throws NoSuchPaddingException  
  72.      * @throws NoSuchAlgorithmException  
  73.      * @throws BadPaddingException  
  74.      * @throws IllegalBlockSizeException  
  75.      * @throws InvalidKeyException  
  76.      */  
  77.     public static void main(String[] args) throws Exception {  
  78.         EncrypDES3 des = new EncrypDES3();  
  79.         String msg ="郭XX-搞笑相声全集";  
  80.         byte[] encontent = des.Encrytor(msg);  
  81.         byte[] decontent = des.Decryptor(encontent);  
  82.         System.out.println("明文是:" + msg);  
  83.         System.out.println("加密后:" + new String(encontent));  
  84.         System.out.println("解密后:" + new String(decontent));  
  85.   
  86.     }  
  87.   
  88. }  


3. AES密码学中的高级加密标准(Advanced Encryption Standard,AES),又称  高级加密标准
Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。   该算法为比利时密码学家Joan Daemen和Vincent Rijmen所设计,结合两位作者的名字,以Rijndael之命名之,投稿高级加密标准的甄选流程。(Rijdael的发音近于 "Rhinedoll"。)

Java代码   收藏代码
  1. import java.security.InvalidKeyException;  
  2. import java.security.NoSuchAlgorithmException;  
  3. import java.security.Security;  
  4.   
  5. import javax.crypto.BadPaddingException;  
  6. import javax.crypto.Cipher;  
  7. import javax.crypto.IllegalBlockSizeException;  
  8. import javax.crypto.KeyGenerator;  
  9. import javax.crypto.NoSuchPaddingException;  
  10. import javax.crypto.SecretKey;  
  11.   
  12. public class EncrypAES {  
  13.       
  14.     //KeyGenerator 提供对称密钥生成器的功能,支持各种算法  
  15.     private KeyGenerator keygen;  
  16.     //SecretKey 负责保存对称密钥  
  17.     private SecretKey deskey;  
  18.     //Cipher负责完成加密或解密工作  
  19.     private Cipher c;  
  20.     //该字节数组负责保存加密的结果  
  21.     private byte[] cipherByte;  
  22.       
  23.     public EncrypAES() throws NoSuchAlgorithmException, NoSuchPaddingException{  
  24.         Security.addProvider(new com.sun.crypto.provider.SunJCE());  
  25.         //实例化支持DES算法的密钥生成器(算法名称命名需按规定,否则抛出异常)  
  26.         keygen = KeyGenerator.getInstance("AES");  
  27.         //生成密钥  
  28.         deskey = keygen.generateKey();  
  29.         //生成Cipher对象,指定其支持的DES算法  
  30.         c = Cipher.getInstance("AES");  
  31.     }  
  32.       
  33.     /** 
  34.      * 对字符串加密 
  35.      *  
  36.      * @param str 
  37.      * @return 
  38.      * @throws InvalidKeyException 
  39.      * @throws IllegalBlockSizeException 
  40.      * @throws BadPaddingException 
  41.      */  
  42.     public byte[] Encrytor(String str) throws InvalidKeyException,  
  43.             IllegalBlockSizeException, BadPaddingException {  
  44.         // 根据密钥,对Cipher对象进行初始化,ENCRYPT_MODE表示加密模式  
  45.         c.init(Cipher.ENCRYPT_MODE, deskey);  
  46.         byte[] src = str.getBytes();  
  47.         // 加密,结果保存进cipherByte  
  48.         cipherByte = c.doFinal(src);  
  49.         return cipherByte;  
  50.     }  
  51.   
  52.     /** 
  53.      * 对字符串解密 
  54.      *  
  55.      * @param buff 
  56.      * @return 
  57.      * @throws InvalidKeyException 
  58.      * @throws IllegalBlockSizeException 
  59.      * @throws BadPaddingException 
  60.      */  
  61.     public byte[] Decryptor(byte[] buff) throws InvalidKeyException,  
  62.             IllegalBlockSizeException, BadPaddingException {  
  63.         // 根据密钥,对Cipher对象进行初始化,DECRYPT_MODE表示加密模式  
  64.         c.init(Cipher.DECRYPT_MODE, deskey);  
  65.         cipherByte = c.doFinal(buff);  
  66.         return cipherByte;  
  67.     }  
  68.   
  69.     /** 
  70.      * @param args 
  71.      * @throws NoSuchPaddingException  
  72.      * @throws NoSuchAlgorithmException  
  73.      * @throws BadPaddingException  
  74.      * @throws IllegalBlockSizeException  
  75.      * @throws InvalidKeyException  
  76.      */  
  77.     public static void main(String[] args) throws Exception {  
  78.         EncrypAES de1 = new EncrypAES();  
  79.         String msg ="郭XX-搞笑相声全集";  
  80.         byte[] encontent = de1.Encrytor(msg);  
  81.         byte[] decontent = de1.Decryptor(encontent);  
  82.         System.out.println("明文是:" + msg);  
  83.         System.out.println("加密后:" + new String(encontent));  
  84.         System.out.println("解密后:" + new String(decontent));  
  85.     }  
  86.   
  87. }  


(二)、非对称加密
1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。相对于“对称加密算法”这种方法也叫做“非对称加密算法”。 与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥
(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

1. RSA 公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
Java代码   收藏代码
  1. import java.security.InvalidKeyException;  
  2. import java.security.KeyPair;  
  3. import java.security.KeyPairGenerator;  
  4. import java.security.NoSuchAlgorithmException;  
  5. import java.security.interfaces.RSAPrivateKey;  
  6. import java.security.interfaces.RSAPublicKey;  
  7.   
  8. import javax.crypto.BadPaddingException;  
  9. import javax.crypto.Cipher;  
  10. import javax.crypto.IllegalBlockSizeException;  
  11. import javax.crypto.NoSuchPaddingException;  
  12.   
  13. public class EncrypRSA {  
  14.       
  15.     /** 
  16.      * 加密 
  17.      * @param publicKey 
  18.      * @param srcBytes 
  19.      * @return 
  20.      * @throws NoSuchAlgorithmException 
  21.      * @throws NoSuchPaddingException 
  22.      * @throws InvalidKeyException 
  23.      * @throws IllegalBlockSizeException 
  24.      * @throws BadPaddingException 
  25.      */  
  26.     protected byte[] encrypt(RSAPublicKey publicKey,byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{  
  27.         if(publicKey!=null){  
  28.             //Cipher负责完成加密或解密工作,基于RSA  
  29.             Cipher cipher = Cipher.getInstance("RSA");  
  30.             //根据公钥,对Cipher对象进行初始化  
  31.             cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
  32.             byte[] resultBytes = cipher.doFinal(srcBytes);  
  33.             return resultBytes;  
  34.         }  
  35.         return null;  
  36.     }  
  37.       
  38.     /** 
  39.      * 解密  
  40.      * @param privateKey 
  41.      * @param srcBytes 
  42.      * @return 
  43.      * @throws NoSuchAlgorithmException 
  44.      * @throws NoSuchPaddingException 
  45.      * @throws InvalidKeyException 
  46.      * @throws IllegalBlockSizeException 
  47.      * @throws BadPaddingException 
  48.      */  
  49.     protected byte[] decrypt(RSAPrivateKey privateKey,byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{  
  50.         if(privateKey!=null){  
  51.             //Cipher负责完成加密或解密工作,基于RSA  
  52.             Cipher cipher = Cipher.getInstance("RSA");  
  53.             //根据公钥,对Cipher对象进行初始化  
  54.             cipher.init(Cipher.DECRYPT_MODE, privateKey);  
  55.             byte[] resultBytes = cipher.doFinal(srcBytes);  
  56.             return resultBytes;  
  57.         }  
  58.         return null;  
  59.     }  
  60.   
  61.     /** 
  62.      * @param args 
  63.      * @throws NoSuchAlgorithmException  
  64.      * @throws BadPaddingException  
  65.      * @throws IllegalBlockSizeException  
  66.      * @throws NoSuchPaddingException  
  67.      * @throws InvalidKeyException  
  68.      */  
  69.     public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {  
  70.         EncrypRSA rsa = new EncrypRSA();  
  71.         String msg = "郭XX-精品相声";  
  72.         //KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象  
  73.         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");  
  74.         //初始化密钥对生成器,密钥大小为1024位  
  75.         keyPairGen.initialize(1024);  
  76.         //生成一个密钥对,保存在keyPair中  
  77.         KeyPair keyPair = keyPairGen.generateKeyPair();  
  78.         //得到私钥  
  79.         RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();               
  80.         //得到公钥  
  81.         RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();  
  82.           
  83.         //用公钥加密  
  84.         byte[] srcBytes = msg.getBytes();  
  85.         byte[] resultBytes = rsa.encrypt(publicKey, srcBytes);  
  86.           
  87.         //用私钥解密  
  88.         byte[] decBytes = rsa.decrypt(privateKey, resultBytes);  
  89.           
  90.         System.out.println("明文是:" + msg);  
  91.         System.out.println("加密后是:" + new String(resultBytes));  
  92.         System.out.println("解密后是:" + new String(decBytes));  
  93.     }  
  94.   
  95. }  


2. DSA
Digital Signature Algorithm (DSA)是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。(感觉有点复杂,没有附代码)
详见 http://63938525.iteye.com/blog/1051565

(三)、题外话 MySQL加密解密函数
MySQL有两个函数来支持这种类型的加密,分别叫做ENCODE()和DECODE()。
下面是一个简单的实例:

Mysql代码   收藏代码
  1. mysql> INSERT INTO users (username,password) VALUES ('joe',ENCODE('guessme','abr'));  
  2.   
  3. Query OK, 1 row affected (0.14 sec)  

其中,Joe的密码是guessme,它通过密钥abracadabra被加密。要注意的是,加密完的结果是一个二进制字符串,如下所示:

提示:虽然ENCODE()和DECODE()这两个函数能够满足大多数的要求,但是有的时候您希望使用强度更高的加密手段。在这种情况下,您可以使用AES_ENCRYPT()和AES_DECRYPT()函数,它们的工作方式是相同的,但是加密强度更高。


单向加密与双向加密不同,一旦数据被加密就没有办法颠倒这一过程。因此密码的验证包括对用户输入内容的重新加密,并将它与保存的密文进行比对,看是否匹配。一种简单的单向加密方式是MD5校验码。MySQL的MD5()函数会为您的数据创建一个“指纹”并将它保存起来,供验证测试使用。下面就是如何使用它的一个简单例子:

Mysql代码   收藏代码
  1. mysql> INSERT INTO users (username,password) VALUES ('joe',MD5('guessme'));  
  2.   
  3. Query OK, 1 row affected (0.00 sec)  



或者,您考虑一下使用ENCRYPT()函数,它使用系统底层的crypt()系统调用来完成加密。这个函数有两个参数:一个是要被加密的字符串,另一个是双(或者多)字符的“salt”。它然后会用salt加密字符串;这个salt然后可以被用来再次加密用户输入的内容,并将它与先前加密的字符串进行比对。下面一个例子说明了如何使用它:

Mysql代码   收藏代码
  1. mysql> INSERT INTO users (username,password) VALUES('joe', ENCRYPT('guessme','ab'));  
  2.   
  3. Query OK, 1 row affected (0.00 sec)  



提示:ENCRYPT()只能用在UNIX、LINIX系统上,因为它需要用到底层的crypt()库。

二、单向加密(信息摘要)
Java一般需要获取对象MessageDigest来实现单项加密(信息摘要)。
1. MD5 即Message-Digest Algorithm 5(信息-摘要算法 5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。
除了MD5以外,其中比较有名的还有sha-1、RIPEMD以及Haval等
Java代码   收藏代码
  1. import java.security.MessageDigest;  
  2. import java.security.NoSuchAlgorithmException;  
  3.   
  4. public class EncrypMD5 {  
  5.       
  6.     public byte[] eccrypt(String info) throws NoSuchAlgorithmException{  
  7.         //根据MD5算法生成MessageDigest对象  
  8.         MessageDigest md5 = MessageDigest.getInstance("MD5");  
  9.         byte[] srcBytes = info.getBytes();  
  10.         //使用srcBytes更新摘要  
  11.         md5.update(srcBytes);  
  12.         //完成哈希计算,得到result  
  13.         byte[] resultBytes = md5.digest();  
  14.         return resultBytes;  
  15.     }  
  16.       
  17.       
  18.     public static void main(String args[]) throws NoSuchAlgorithmException{  
  19.         String msg = "郭XX-精品相声技术";  
  20.         EncrypMD5 md5 = new EncrypMD5();  
  21.         byte[] resultBytes = md5.eccrypt(msg);  
  22.           
  23.         System.out.println("密文是:" + new String(resultBytes));  
  24.         System.out.println("明文是:" + msg);  
  25.     }  
  26.   
  27. }  


2. SHA 是一种数据加密算法,该算法经过加密专家多年来的发展和改进已日益完善,现在已成为公认的最安全的散列算法之一,并被广泛使用。该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。散列函数值可以说时对明文的一种“指纹”或是“摘要”所以对散列值的数字签名就可以视为对此明文的数字签名。

Java代码   收藏代码
  1. import java.security.MessageDigest;  
  2. import java.security.NoSuchAlgorithmException;  
  3.   
  4. public class EncrypSHA {  
  5.       
  6.     public byte[] eccrypt(String info) throws NoSuchAlgorithmException{  
  7.         MessageDigest md5 = MessageDigest.getInstance("SHA");  
  8.         byte[] srcBytes = info.getBytes();  
  9.         //使用srcBytes更新摘要  
  10.         md5.update(srcBytes);  
  11.         //完成哈希计算,得到result  
  12.         byte[] resultBytes = md5.digest();  
  13.         return resultBytes;  
  14.     }  
  15.   
  16.     /** 
  17.      * @param args 
  18.      * @throws NoSuchAlgorithmException  
  19.      */  
  20.     public static void main(String[] args) throws NoSuchAlgorithmException {  
  21.         String msg = "郭XX-精品相声技术";  
  22.         EncrypSHA sha = new EncrypSHA();  
  23.         byte[] resultBytes = sha.eccrypt(msg);  
  24.         System.out.println("明文是:" + msg);  
  25.         System.out.println("密文是:" + new String(resultBytes));  
  26.           
  27.     }  
  28.   
  29. }  


附件中是以上几种的源代码,附带额外的两种使用方式。

增加一种关于文件的哈希算法源代码:
Java代码   收藏代码
  1. import java.io.FileInputStream;  
  2. import java.io.InputStream;  
  3. import java.security.MessageDigest;  
  4.   
  5. public class FileHashUtil {  
  6.   
  7.     public static final char[] hexChar = {   
  8.             '0''1''2''3''4''5''6''7''8''9''a''b''c''d''e''f' };  
  9.     public static final String[] hashTypes = new String[] { "MD2""MD5""SHA1""SHA-256""SHA-384""SHA-512" };  
  10.       
  11.     public void MD5File(String fileName) throws Exception{  
  12.         //String fileName = args[0];  
  13.         System.out.println("需要获取hash的文件为: " + fileName);  
  14.         java.util.List<MessageDigest> mds = new java.util.ArrayList<MessageDigest>();  
  15.         for (String hashType : hashTypes) {  
  16.             MessageDigest md = MessageDigest.getInstance(hashType);  
  17.             mds.add(md);  
  18.         }  
  19.         InputStream fis = null;  
  20.         try {  
  21.             fis = new FileInputStream(fileName);  
  22.             byte[] buffer = new byte[1024];  
  23.             int numRead = 0;  
  24.             while ((numRead = fis.read(buffer)) > 0) {  
  25.                 for (MessageDigest md : mds) {  
  26.                     md.update(buffer, 0, numRead);  
  27.                 }  
  28.             }  
  29.         } catch (Exception ex) {  
  30.             ex.printStackTrace();  
  31.         } finally {  
  32.             if (fis != null) {  
  33.                 fis.close();  
  34.             }  
  35.         }  
  36.         for (MessageDigest md : mds) {  
  37.             System.out.println(md.getAlgorithm() + " == " + toHexString(md.digest()));  
  38.         }  
  39.     }  
  40.       
  41.   
  42.     public static void main(String[] args) throws Exception {  
  43.         String[] fileName = new String[] {"D:/hapfish/ShellFolder.java","D:/hapfish/ShellFolder - 副本.java",  
  44.                   "E:/ShellFolder - 副本.java","E:/ShellFolder.txt","D:/hapfish/ShellFolder.jpg",  
  45.                   "E:/ShellFolder增加字符.txt","D:/hapfish/birosoft.jar"};  
  46.         FileHashUtil files  = new FileHashUtil();  
  47.         for(int i=0;i<fileName.length;i++){  
  48.             files.MD5File(fileName[i]);  
  49.         }   
  50.           
  51.           
  52.     }  
  53.   
  54.     public static String toHexString(byte[] b) {  
  55.         StringBuilder sb = new StringBuilder(b.length * 2);  
  56.         for (int i = 0; i < b.length; i++) {  
  57.             sb.append(hexChar[(b[i] & 0xf0) >>> 4]);  
  58.             sb.append(hexChar[b[i] & 0x0f]);  
  59.         }  
  60.         return sb.toString();  
  61.     }  
  62.   
  63. }  


运行说明
说明代码   收藏代码
  1. "D:/hapfish/ShellFolder.java",  
  2. "D:/hapfish/ShellFolder - 副本.java",  
  3. "E:/ShellFolder - 副本.java",  
  4. "E:/ShellFolder.txt",  
  5. "D:/hapfish/ShellFolder.jpg",  
  6. 以上五个文件是同一文件经过复制、改扩展名的,最后计算哈希结果是一致的。  
  7.   
  8. "E:/ShellFolder增加字符.txt" 增加了几个字符串,就不一样了  
  9.   
  10. "D:/hapfish/birosoft.jar" 完全不相关的另外一个文件  


运行结果:
Java代码   收藏代码
  1. 需要获取hash的文件为: D:/hapfish/ShellFolder.java  
  2. MD2 == 3a755a99c5e407005cd45ebd856b4649  
  3. MD5 == 5d08d440fa911d1e418c69a90b83cd86  
  4. SHA1 == 522c8c4f4ff1dd669e251c2ab854c3033a51ca63  
  5. SHA-256 == d1feb0c73c10a759e88bd240cb9d56d0598b4ff83a0704c6679f7ba12f6c4d99  
  6. SHA-384 == 8f8c9da4cd7241c58af3c52b49199033f2dcf3d67f421753999f87511618d9ea2d738e8c16b9b68a7572d06108ff10f6  
  7. SHA-512 == 4711579daee3ddacbaea189310348956cb43bcaaf0099f3be047b06f16c1a20a6b71ee3a4ee018128d647e9f2ef0d644747672238e49a8da3d0cd26dfe597458  
  8. 需要获取hash的文件为: D:/hapfish/ShellFolder - 副本.java  
  9. MD2 == 3a755a99c5e407005cd45ebd856b4649  
  10. MD5 == 5d08d440fa911d1e418c69a90b83cd86  
  11. SHA1 == 522c8c4f4ff1dd669e251c2ab854c3033a51ca63  
  12. SHA-256 == d1feb0c73c10a759e88bd240cb9d56d0598b4ff83a0704c6679f7ba12f6c4d99  
  13. SHA-384 == 8f8c9da4cd7241c58af3c52b49199033f2dcf3d67f421753999f87511618d9ea2d738e8c16b9b68a7572d06108ff10f6  
  14. SHA-512 == 4711579daee3ddacbaea189310348956cb43bcaaf0099f3be047b06f16c1a20a6b71ee3a4ee018128d647e9f2ef0d644747672238e49a8da3d0cd26dfe597458  
  15. 需要获取hash的文件为: E:/ShellFolder - 副本.java  
  16. MD2 == 3a755a99c5e407005cd45ebd856b4649  
  17. MD5 == 5d08d440fa911d1e418c69a90b83cd86  
  18. SHA1 == 522c8c4f4ff1dd669e251c2ab854c3033a51ca63  
  19. SHA-256 == d1feb0c73c10a759e88bd240cb9d56d0598b4ff83a0704c6679f7ba12f6c4d99  
  20. SHA-384 == 8f8c9da4cd7241c58af3c52b49199033f2dcf3d67f421753999f87511618d9ea2d738e8c16b9b68a7572d06108ff10f6  
  21. SHA-512 == 4711579daee3ddacbaea189310348956cb43bcaaf0099f3be047b06f16c1a20a6b71ee3a4ee018128d647e9f2ef0d644747672238e49a8da3d0cd26dfe597458  
  22. 需要获取hash的文件为: E:/ShellFolder.txt  
  23. MD2 == 3a755a99c5e407005cd45ebd856b4649  
  24. MD5 == 5d08d440fa911d1e418c69a90b83cd86  
  25. SHA1 == 522c8c4f4ff1dd669e251c2ab854c3033a51ca63  
  26. SHA-256 == d1feb0c73c10a759e88bd240cb9d56d0598b4ff83a0704c6679f7ba12f6c4d99  
  27. SHA-384 == 8f8c9da4cd7241c58af3c52b49199033f2dcf3d67f421753999f87511618d9ea2d738e8c16b9b68a7572d06108ff10f6  
  28. SHA-512 == 4711579daee3ddacbaea189310348956cb43bcaaf0099f3be047b06f16c1a20a6b71ee3a4ee018128d647e9f2ef0d644747672238e49a8da3d0cd26dfe597458  
  29. 需要获取hash的文件为: D:/hapfish/ShellFolder.jpg  
  30. MD2 == 3a755a99c5e407005cd45ebd856b4649  
  31. MD5 == 5d08d440fa911d1e418c69a90b83cd86  
  32. SHA1 == 522c8c4f4ff1dd669e251c2ab854c3033a51ca63  
  33. SHA-256 == d1feb0c73c10a759e88bd240cb9d56d0598b4ff83a0704c6679f7ba12f6c4d99  
  34. SHA-384 == 8f8c9da4cd7241c58af3c52b49199033f2dcf3d67f421753999f87511618d9ea2d738e8c16b9b68a7572d06108ff10f6  
  35. SHA-512 == 4711579daee3ddacbaea189310348956cb43bcaaf0099f3be047b06f16c1a20a6b71ee3a4ee018128d647e9f2ef0d644747672238e49a8da3d0cd26dfe597458  
  36. 需要获取hash的文件为: E:/ShellFolder增加字符.txt  
  37. MD2 == f2717c24c6c0e110457bd17221c9ca6c  
  38. MD5 == c49e353a7c4c26bd7ccb5e90917c230f  
  39. SHA1 == 477c8a9e465bfaa4be42d35c032a17f7e6b42b97  
  40. SHA-256 == 9fa18adaf242ebcdc6563922d84c2a163c82e1a24db2eb2b73978ed1f354a8a3  
  41. SHA-384 == 4eee8f8e6d64d21c15dc01fa049f4d12a3b8e1d94d87763fe0bea75ab5ea8432fa8251289ece45ee39fe3d36b3c3020c  
  42. SHA-512 == e852ec0ff77250be497389d2f5a1818c18bb66106b9905c4ee26fe0d256eb3b77e0ce9a28a84e4b67e4332ba37ec3aa7518148e3a682318c0fc34c391f45c201  
  43. 需要获取hash的文件为: D:/hapfish/birosoft.jar  
  44. MD2 == 38c5e1404718916dec59c33cafc909b3  
  45. MD5 == dc3e2cc4fb3949cf3660e0f5f8c3fba3  
  46. SHA1 == cde3dc25498afc5a563af0bb0eb54dc45f71bb28  
  47. SHA-256 == adf6a961c70c6ea677dff066fc5d896fb0beb4dd442ca0eb619ae1d1b04291e5  
  48. SHA-384 == fe7c6b754893c53ebd82bb53703fb5cc32115c9a38f98072f73def90729b271ee3c5c78e258bd9ff5ee5476193c2178b  
  49. SHA-512 == a15376f327256a6e049dfbdc5c2ad3a98bffccc6fa92ee01ff53db6b04471ca0f45ca28f76ff4a6911b57825afa046671299141f2499d71f1dac618c92385491  


最后,把运行结果贴出来有点占空间,主要为了说明表述自己的猜想。一般来说同一哈希算法对同一文件(镜像、扩展名被修改)所产生的结果应该是一致的。

因此有个猜想,在baidu文库、腾讯的群共享上传时,先会判断是否有相同文件,从某种可能上来说也采用了对文件的哈希算法,毕竟从本地运算一个哈希算法后获得的数值要比把整个文件传过去比较实惠得多。而且字符串的比较也是很方便的。

对于某一种哈希算法,存在一种可能:就是两个不同的文件,计算出来的哈希值可能是一样的。当然为了保险,可以用两种甚至更多的哈希算法,只有在每种算法获得的哈希值都相同时,才能判断是同一个文件。
如果我们也对用户上传的文件进行哈希计算的话,就可以节省资源,同样的文件按理说可以减少上传次数……
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java SE Platform 软件包 java.applet 提供创建 applet 所必需的类和 applet 用来与其 applet 上下文通信的类。 java.awt 包含用于创建用户界面和绘制图形图像的所有类。 java.awt.color 提供用于颜色空间的类。 java.awt.datatransfer 提供在应用程序之间和在应用程序内部传输数据的接口和类。 java.awt.dnd Drag 和 Drop 是一种直接操作动作,在许多图形用户界面系统都会遇到它,它提供了一种机制,能够在两个与 GUI 显示元素逻辑相关的实体之间传输信息。 java.awt.event 提供处理由 AWT 组件所激发的各类事件的接口和类。 java.awt.font 提供与字体相关的类和接口。 java.awt.geom 提供用于在与二维几何形状相关的对象上定义和执行操作的 Java 2D 类。 java.awt.im 提供输入方法框架所需的类和接口。 java.awt.im.spi 提供启用可以与 Java 运行时环境一起使用的输入方法开发的接口。 java.awt.image 提供创建和修改图像的各种类。 java.awt.image.renderable 提供用于生成与呈现无关的图像的类和接口。 java.awt.print 为通用的打印 API 提供类和接口。 java.beans 包含与开发 beans 有关的类,即基于 JavaBeansTM 架构的组件。 java.beans.beancontext 提供与 bean 上下文有关的类和接口。 java.io 通过数据流、序列化和文件系统提供系统输入和输出。 java.lang 提供利用 Java 编程语言进行程序设计的基础类。 java.lang.annotation 为 Java 编程语言注释设施提供库支持。 java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供了引用对象类,支持在某种程度上与垃圾回收器之间的交互。 java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java.nio 定义作为数据容器的缓冲区,并提供其他 NIO 包的概述。 java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务提供者类。 java.nio.charset 定义用来在字节和 Unicode 字符之间转换的 charset、解码器和编码器。 java.nio.charset.spi java.nio.charset 包的服务提供者类。 java.rmi 提供 RMI 包。 java.rmi.activation 为 RMI 对象激活提供支持。 java.rmi.dgc 为 RMI 分布式垃圾回收提供了类和接口。 java.rmi.registry 提供 RMI 注册表的一个类和两个接口。 java.rmi.server 提供支持服务器端 RMI 的类和接口。 java.security 为安全框架提供类和接口。 java.security.acl 此包的类和接口已经被 java.security 包的类取代。 java.security.cert 提供用于解析和管理证书、证书撤消列表 (CRL) 和证书路径的类和接口。 java.security.interfaces 提供的接口用于生成 RSA Laboratory Technical Note PKCS#1 定义的 RSA(Rivest、Shamir 和 Adleman AsymmetricCipher 算法)密钥,以及 NIST 的 FIPS-186 定义的 DSA(数字签名算法)密钥。 java.security.spec 提供密钥规范和算法参数规范的类和接口。 java.sql 提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)的数据的 API。 java.text 提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。 java.text.spi java.text 包类的服务提供者类。 java.util 包含 collection 框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组)。 java.util.concurrent 在并发编程常用的实用工具类。 java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。 java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序存储并获取用户和系统首选项和配置数据。 java.util.regex 用于匹配字符序列与正则表达式指定模式的类。 java.util.spi java.util 包类的服务提供者类。 java.util.zip 提供用于读写标准 ZIP 和 GZIP 文件格式的类。 javax.accessibility 定义了用户界面组件与提供对这些组件进行访问的辅助技术之间的协定。 javax.crypto 为加密操作提供类和接口。 javax.crypto.interfaces 根据 RSA Laboratories' PKCS #3 的定义,提供 Diffie-Hellman 密钥接口。 javax.crypto.spec 为密钥规范和算法参数规范提供类和接口。 javax.imageio Java Image I/O API 的主要包。 javax.imageio.event Java Image I/O API 的一个包,用于在读取和写入图像期间处理事件的同步通知。 javax.imageio.metadata 用于处理读写元数据的 Java Image I/O API 的包。 javax.imageio.plugins.bmp 包含供内置 BMP 插件使用的公共类的包。 javax.imageio.plugins.jpeg 支持内置 JPEG 插件的类。 javax.imageio.spi 包含用于 reader、writer、transcoder 和流的插件接口以及一个运行时注册表的 Java Image I/O API 包。 javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流产生的低级别 I/O。 javax.management 提供 Java Management Extensions 的核心类。 javax.management.loading 提供实现高级动态加载的类。 javax.management.modelmbean 提供了 ModelMBean 类的定义。 javax.management.monitor 提供 monitor 类的定义。 javax.management.openmbean 提供开放数据类型和 Open MBean 描述符类。 javax.management.relation 提供 Relation Service 的定义。 javax.management.remote 对 JMX MBean 服务器进行远程访问使用的接口。 javax.management.remote.rmi RMI 连接器是供 JMX Remote API 使用的一种连接器,后者使用 RMI 将客户端请求传输到远程 MBean 服务器。 javax.management.timer 提供对 Timer MBean(计时器 MBean)的定义。 javax.naming 为访问命名服务提供类和接口。 javax.naming.directory 扩展 javax.naming 包以提供访问目录服务的功能。 javax.naming.event 在访问命名和目录服务时提供对事件通知的支持。 javax.naming.ldap 提供对 LDAPv3 扩展操作和控件的支持。 javax.naming.spi 提供一些方法来动态地插入对通过 javax.naming 和相关包访问命名和目录服务的支持。 javax.net 提供用于网络应用程序的类。 javax.net.ssl 提供用于安全套接字包的类。 javax.print 为 JavaTM Print Service API 提供了主要类和接口。 javax.print.attribute 提供了描述 JavaTM Print Service 属性的类型以及如何分类这些属性的类和接口。 javax.print.attribute.standard 包 javax.print.attribute.standard 包括特定打印属性的类。 javax.print.event 包 javax.print.event 包含事件类和侦听器接口。 javax.rmi 包含 RMI-IIOP 的用户 API。 javax.rmi.CORBA 包含用于 RMI-IIOP 的可移植性 API。 javax.rmi.ssl 通过安全套接字层 (SSL) 或传输层安全 (TLS) 协议提供 RMIClientSocketFactory 和 RMIServerSocketFactory 的实现。 javax.security.auth 此包提供用于进行验证和授权的框架。 javax.security.auth.callback 此包提供与应用程序进行交互所必需的类,以便检索信息(例如,包括用户名和密码的验证数据)或显示信息(例如,错误和警告消息)。 javax.security.auth.kerberos 此包包含与 Kerberos 网络验证协议相关的实用工具类。 javax.security.auth.login 此包提供可插入的验证框架。 javax.security.auth.spi 此包提供用于实现可插入验证模块的接口。 javax.security.auth.x500 此包包含应该用来在 Subject 存储 X500 Principal 和 X500 Private Crendentials 的类。 javax.security.cert 为公钥证书提供类。 javax.security.sasl 包含用于支持 SASL 的类和接口。 javax.sound.midi 提供用于 MIDI(音乐乐器数字接口)数据的 I/O、序列化和合成的接口和类。 javax.sound.midi.spi 在提供新的 MIDI 设备、MIDI 文件 reader 和 writer、或音库 reader 时提供服务提供者要实现的接口。 javax.sound.sampled 提供用于捕获、处理和回放取样的音频数据的接口和类。 javax.sound.sampled.spi 在提供新音频设备、声音文件 reader 和 writer,或音频格式转换器时,提供将为其创建子类的服务提供者的抽象类。 javax.sql 为通过 JavaTM 编程语言进行服务器端数据源访问和处理提供 API。 javax.sql.rowset JDBC RowSet 实现的标准接口和基类。 javax.sql.rowset.serial 提供实用工具类,允许 SQL 类型与 Java 编程语言数据类型之间的可序列化映射关系。 javax.sql.rowset.spi 第三方供应商在其同步提供者的实现必须使用的标准类和接口。 javax.swing 提供一组“轻量级”(全部是 Java 语言)组件,尽量让这些组件在所有平台上的工作方式都相同。 javax.swing.border 提供围绕 Swing 组件绘制特殊边框的类和接口。 javax.swing.colorchooser 包含供 JColorChooser 组件使用的类和接口。 javax.swing.event 供 Swing 组件触发的事件使用。 javax.swing.filechooser 包含 JFileChooser 组件使用的类和接口。 javax.swing.plaf 提供一个接口和许多抽象类,Swing 用它们来提供自己的可插入外观功能。 javax.swing.plaf.basic 提供了根据基本外观构建的用户界面对象。 javax.swing.plaf.metal 提供根据 Java 外观(曾经代称为 Metal)构建的用户界面对象,Java 外观是默认外观。 javax.swing.plaf.multi 提供了组合两个或多个外观的用户界面对象。 javax.swing.plaf.synth Synth 是一个可更换皮肤 (skinnable) 的外观,在其可委托所有绘制。 javax.swing.table 提供用于处理 javax.swing.JTable 的类和接口。 javax.swing.text 提供类 HTMLEditorKit 和创建 HTML 文本编辑器的支持类。 javax.swing.text.html 提供类 HTMLEditorKit 和创建 HTML 文本编辑器的支持类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值