精华内容
下载资源
问答
  • Java加密技术(四)——非对称加密算法RSA 非对称加密算法——RSA 基本概念 非对称加密算法是一种密钥的保密方法。 非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有...

    Java加密技术(四)——非对称加密算法RSA

    非对称加密算法——RSA 基本概念

             非对称加密算法是一种密钥的保密方法。

             非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。

              另一方面,甲方可以使用乙方的公钥对机密信息进行签名后再发送给乙方;乙方再用自己的私匙对数据进行验签。

    甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。 非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。

    非对称密码体制的特点:

    算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。

    工作原理

    1.A要向B发送信息,A和B都要产生一对用于加密和解密的公钥和私钥。

    2.A的私钥保密,A的公钥告诉B;B的私钥保密,B的公钥告诉A。

    3.A要给B发送信息时,A用B的公钥加密信息,因为A知道B的公钥。

    4.A将这个消息发给B(已经用B的公钥加密消息)。

    5.B收到这个消息后,B用自己的私钥解密A的消息。其他所有收到这个报文的人都无法解密,因为只有B才有B的私钥。

    RSA 

        这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。 

        这种加密算法的特点主要是密钥的变化,上文我们看到DES只有一个密钥。相当于只有一把钥匙,如果这把钥匙丢了,数据也就不安全了。RSA同时有两把钥匙,公钥与私钥。同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验。确保数据在传输工程中不被修改。 

    流程分析: 

    1. 甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。

    2. 甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效,如果有效使用公钥对数据解密。

    3. 乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。

    按如上步骤给出序列图,如下: 

     

     

     

    Demo

    import java.security.Key;  

    import java.security.KeyFactory;  

    import java.security.KeyPair;  

    import java.security.KeyPairGenerator;  

    import java.security.PrivateKey;  

    import java.security.PublicKey;  

    import java.security.Signature;  

    import java.security.interfaces.RSAPrivateKey;  

    import java.security.interfaces.RSAPublicKey;  

    import java.security.spec.PKCS8EncodedKeySpec;  

    import java.security.spec.X509EncodedKeySpec;  

      

    import java.util.HashMap;  

    import java.util.Map;  

      

    import javax.crypto.Cipher;  

      

    /** 

     * RSA安全编码组件 

     *  

     * @author Sunny 

     * @version 1.0 

     * @since 1.0 

     */  

    public abstract class RSACoder extends Coder {  

        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";  

      

        /** 

         * 用私钥对信息生成数字签名 

         *  

         * @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 = KeyFactory.getInstance(KEY_ALGORITHM);  

      

            // 取私钥匙对象  

            PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);  

      

            // 用私钥对信息生成数字签名  

            Signature signature = Signature.getInstance(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 = KeyFactory.getInstance(KEY_ALGORITHM);  

      

            // 取公钥匙对象  

            PublicKey pubKey = keyFactory.generatePublic(keySpec);  

      

            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);  

            signature.initVerify(pubKey);  

            signature.update(data);  

      

            // 验证签名是否正常  

            return signature.verify(decryptBASE64(sign));  

        }  

      

        /** 

         * 解密<br> 

         * 用私钥解密 

         *  

         * @param data 

         * @param key 

         * @return 

         * @throws Exception 

         */  

        public static byte[] decryptByPrivateKey(byte[] data, String key)  

                throws Exception {  

            // 对密钥解密  

            byte[] keyBytes = decryptBASE64(key);  

      

            // 取得私钥  

            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);  

            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  

            Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);  

      

            // 对数据解密  

            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());  

            cipher.init(Cipher.DECRYPT_MODE, privateKey);  

      

            return cipher.doFinal(data);  

        }  

      

        /** 

         * 解密<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 = KeyFactory.getInstance(KEY_ALGORITHM);  

            Key publicKey = keyFactory.generatePublic(x509KeySpec);  

      

            // 对数据解密  

            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());  

            cipher.init(Cipher.DECRYPT_MODE, publicKey);  

      

            return cipher.doFinal(data);  

        }  

      

        /** 

         * 加密<br> 

         * 用公钥加密 

         *  

         * @param data 

         * @param key 

         * @return 

         * @throws Exception 

         */  

        public static byte[] encryptByPublicKey(byte[] data, String key)  

                throws Exception {  

            // 对公钥解密  

            byte[] keyBytes = decryptBASE64(key);  

      

            // 取得公钥  

            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);  

            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  

            Key publicKey = keyFactory.generatePublic(x509KeySpec);  

      

            // 对数据加密  

            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());  

            cipher.init(Cipher.ENCRYPT_MODE, publicKey);  

      

            return cipher.doFinal(data);  

        }  

      

        /** 

         * 加密<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 = KeyFactory.getInstance(KEY_ALGORITHM);  

            Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);  

      

            // 对数据加密  

            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());  

            cipher.init(Cipher.ENCRYPT_MODE, privateKey);  

      

            return cipher.doFinal(data);  

        }  

      

        /** 

         * 取得私钥 

         *  

         * @param keyMap 

         * @return 

         * @throws Exception 

         */  

        public static String getPrivateKey(Map<String, Object> keyMap)  

                throws Exception {  

            Key key = (Key) keyMap.get(PRIVATE_KEY);  

      

            return encryptBASE64(key.getEncoded());  

        }  

      

        /** 

         * 取得公钥 

         *  

         * @param keyMap 

         * @return 

         * @throws Exception 

         */  

        public static String getPublicKey(Map<String, Object> keyMap)  

                throws Exception {  

            Key key = (Key) keyMap.get(PUBLIC_KEY);  

      

            return encryptBASE64(key.getEncoded());  

        }  

      

        /** 

         * 初始化密钥 

         *  

         * @return 

         * @throws Exception 

         */  

        public static Map<String, Object> initKey() throws Exception {  

            KeyPairGenerator keyPairGen = KeyPairGenerator  

                    .getInstance(KEY_ALGORITHM);  

            keyPairGen.initialize(1024);  

      

            KeyPair keyPair = keyPairGen.generateKeyPair();  

      

            // 公钥  

            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  

      

            // 私钥  

            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();  

      

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

      

            keyMap.put(PUBLIC_KEY, publicKey);  

            keyMap.put(PRIVATE_KEY, privateKey);  

            return keyMap;  

        }  

    }  

     

    再给出一个测试类: 

     

    import static org.junit.Assert.*;  

      

    import org.junit.Before;  

    import org.junit.Test;  

      

    import java.util.Map;  

      

    /** 

     *  

     * @author Sunny 

     * @version 1.0 

     * @since 1.0 

     */  

    public class RSACoderTest {  

        private String publicKey;  

        private String privateKey;  

      

        @Before  

        public void setUp() throws Exception {  

            Map<String, Object> keyMap = RSACoder.initKey();  

      

            publicKey = RSACoder.getPublicKey(keyMap);  

            privateKey = RSACoder.getPrivateKey(keyMap);  

            System.err.println("公钥: \n\r" + publicKey);  

            System.err.println("私钥: \n\r" + privateKey);  

        }  

      

        @Test  

        public void test() throws Exception {  

            System.err.println("公钥加密——私钥解密");  

            String inputStr = "abc";  

            byte[] data = inputStr.getBytes();  

      

            byte[] encodedData = RSACoder.encryptByPublicKey(data, publicKey);  

      

            byte[] decodedData = RSACoder.decryptByPrivateKey(encodedData,  

                    privateKey);  

      

            String outputStr = new String(decodedData);  

            System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);  

            assertEquals(inputStr, outputStr);  

      

        }  

      

        @Test  

        public void testSign() throws Exception {  

            System.err.println("私钥加密——公钥解密");  

            String inputStr = "sign";  

            byte[] data = inputStr.getBytes();  

      

            byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);  

      

            byte[] decodedData = RSACoder  

                    .decryptByPublicKey(encodedData, publicKey);  

      

            String outputStr = new String(decodedData);  

            System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);  

            assertEquals(inputStr, outputStr);  

      

            System.err.println("私钥签名——公钥验证签名");  

            // 产生签名  

            String sign = RSACoder.sign(encodedData, privateKey);  

            System.err.println("签名:\r" + sign);  

      

            // 验证签名  

            boolean status = RSACoder.verify(encodedData, publicKey, sign);  

            System.err.println("状态:\r" + status);  

            assertTrue(status);  

        }  

    }  

     

    控制台输出: 

    公钥:   

     

    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYU/+I0+z1aBl5X6DUUOHQ7FZpmBSDbKTtx89J  

    EcB64jFCkunELT8qiKly7fzEqD03g8ALlu5XvX+bBqHFy7YPJJP0ekE2X3wjUnh2NxlqpH3/B/xm  

    1ZdSlCwDIkbijhBVDjA/bu5BObhZqQmDwIxlQInL9oVz+o6FbAZCyHBd7wIDAQAB  

      

    私钥:   

      

    MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhT/4jT7PVoGXlfoNRQ4dDsVmmY  

    FINspO3Hz0kRwHriMUKS6cQtPyqIqXLt/MSoPTeDwAuW7le9f5sGocXLtg8kk/R6QTZffCNSeHY3  

    GWqkff8H/GbVl1KULAMiRuKOEFUOMD9u7kE5uFmpCYPAjGVAicv2hXP6joVsBkLIcF3vAgMBAAEC  

    gYBvZHWoZHmS2EZQqKqeuGr58eobG9hcZzWQoJ4nq/CarBAjw/VovUHE490uK3S9ht4FW7Yzg3LV  

    /MB06Huifh6qf/X9NQA7SeZRRC8gnCQk6JuDIEVJOud5jU+9tyumJakDKodQ3Jf2zQtNr+5ZdEPl  

    uwWgv9c4kmpjhAdyMuQmYQJBANn6pcgvyYaia52dnu+yBUsGkaFfwXkzFSExIbi0MXTkhEb/ER/D  

    rLytukkUu5S5ecz/KBa8U4xIslZDYQbLz5ECQQCy5dutt7RsxN4+dxCWn0/1FrkWl2G329Ucewm3  

    QU9CKu4D+7Kqdj+Ha3lXP8F0Etaaapi7+EfkRUpukn2ItZV/AkEAlk+I0iphxT1rCB0Q5CjWDY5S  

    Df2B5JmdEG5Y2o0nLXwG2w44OLct/k2uD4cEcuITY5Dvi/4BftMCZwm/dnhEgQJACIktJSnJwxLV  

    o9dchENPtlsCM9C/Sd2EWpqISSUlmfugZbJBwR5pQ5XeMUqKeXZYpP+HEBj1nS+tMH9u2/IGEwJA  

    fL8mZiZXan/oBKrblAbplNcKWGRVD/3y65042PAEeghahlJMiYquV5DzZajuuT0wbJ5xQuZB01+X  

    nfpFpBJ2dw==  

      

    公钥加密——私钥解密  

    加密前: abc  

      

    解密后: abc  

    公钥:   

      

    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdOj40yEB48XqWxmPILmJAc7UecIN7F32etSHF  

    9rwbuEh3+iTPOGSxhoSQpOED0vOb0ZIMkBXZSgsxLaBSin2RZ09YKWRjtpCA0kDkiD11gj4tzTiM  

    l9qq1kwSK7ZkGAgodEn3yIILVmQDuEImHOXFtulvJ71ka07u3LuwUNdB/wIDAQAB  

      

    私钥:   

      

    MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN06PjTIQHjxepbGY8guYkBztR5w  

    g3sXfZ61IcX2vBu4SHf6JM84ZLGGhJCk4QPS85vRkgyQFdlKCzEtoFKKfZFnT1gpZGO2kIDSQOSI  

    PXWCPi3NOIyX2qrWTBIrtmQYCCh0SffIggtWZAO4QiYc5cW26W8nvWRrTu7cu7BQ10H/AgMBAAEC  

    gYEAz2JWBizjI31bqhP4XiP9PuY5F3vqBW4T+L9cFbQiyumKJc58yzTWUAUGKIIn3enXLG7dNqGr  

    mbJro4JeFIJ3CiVDpXR9+FluIgI4SXm7ioGKF2NOMA9LR5Fu82W+pLfpTN2y2SaLYWEDZyp53BxY  

    j9gUxaxi1MQs+C1ZgDF2xmECQQDy70bQntbRfysP+ppCtd56YRnES1Tyekw0wryS2tr+ivQJl7JF  

    gp5rPAOXpgrq36xHDwUspQ0sJ0vj0O7ywxr1AkEA6SAaLhrJJrYucC0jxwAhUYyaPN+aOsWymaRh  

    9jA/Wc0wp29SbGTh5CcMuGpXm1g0M+FKW3dGiHgS3rVUKim4owJAbnxgapUzAgiiHxxMeDaavnHW  

    9C2GrtjsO7qtZOTgYI/1uT8itvZW8lJTF+9OW8/qXE76fXl7ai9dFnl5kzMk2QJBALfHz/vCsArt  

    mkRiwY6zApE4Z6tPl1V33ymSVovvUzHnOdD1SKQdD5t+UV/crb3QVi8ED0t2B0u0ZSPfDT/D7kMC  

    QDpwdj9k2F5aokLHBHUNJPFDAp7a5QMaT64gv/d48ITJ68Co+v5WzLMpzJBYXK6PAtqIhxbuPEc2  

    I2k1Afmrwyw=  

      

    私钥加密——公钥解密  

    加密前: sign  

      

    解密后: sign  

    私钥签名——公钥验证签名  

    签名:  

    ud1RsIwmSC1pN22I4IXteg1VD2FbiehKUfNxgVSHzvQNIK+d20FCkHCqh9djP3h94iWnIUY0ifU+  

    mbJkhAl/i5krExOE0hknOnPMcEP+lZV1RbJI2zG2YooSp2XDleqrQk5e/QF2Mx0Zxt8Xsg7ucVpn  

    i3wwbYWs9wSzIf0UjlM=  

      

    状态:  

    true  

    总结

        简要总结一下,使用公钥加密、私钥解密,完成了乙方到甲方的一次数据传递,通过私钥加密、公钥解密,同时通过私钥签名、公钥验证签名,完成了一次甲方到乙方的数据传递与验证,两次数据传递完成一整套的数据交互! 

     

    类似数字签名,数字信封是这样描述的: 

     

    数字信封 

      数字信封用加密技术来保证只有特定的收信人才能阅读信的内容。 

    流程: 

        信息发送方采用对称密钥来加密信息,然后再用接收方的公钥来加密此对称密钥(这部分称为数字信封),再将它和信息一起发送给接收方;接收方先用相应的私钥打开数字信封,得到对称密钥,然后使用对称密钥再解开信息。 

     

    展开全文
  • Java 加密技术

    千次阅读 多人点赞 2019-09-16 10:32:11
    Java加密算法 JDK中带有部分加密算法的实现类,主要的是java.security和javax.crypto包下的类,还可以使用Bouncy Castle(丰富JDK中加密算法的不足)jar包是:bcprov-jdk15on-1.57.jar和Commons Codec(简化JDK中...
    Java加密算法

    JDK中带有部分加密算法的实现类,主要的是java.security和javax.crypto包下的类,还可以使用Bouncy Castle(丰富JDK中加密算法的不足)jar包是:bcprov-jdk15on-1.57.jar和Commons Codec(简化JDK中加密的操作)jar包是:commons-codec-1.10.jar

    Base64

    Base64用于网络中传输的数据进行编码,严格意义上属于编码的格式,有64个字符的对应的编码,Base64就是将内容按照该格式进行编码。可以对数据编码和解码,是可逆的,安全度较低,不过,也可以作为最基础最简单的加密算法用于加密要求较弱的情况

    Base64可以使用JDk中自带的类实现,还可以使用Bouncy Castle(简称bc)或Commons Codec(简称cc)实现

    加密数据:

    private static String src="Hello Base64";
    

    导入的类:

    import java.io.IOException;
    
    import org.apache.commons.codec.binary.Base64;
    
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    

    JDk实现主要使用用BASE64Encoder和BASE64Decoder类的方法(注意:在Eclipse中使用JDK的Base64可能会出现找不到的问题,是因为Base64Encoder并不属于JDK标准库范畴,但是又包含在了JDK中,需要我们手动导入\jre\lib目录下的rt.jar包即可):

    public static void jdkBase64(){
            try {
                BASE64Encoder encoder=new BASE64Encoder();
                String encode = encoder.encode(src.getBytes());
                System.out.println("encode: "+encode);
                
                BASE64Decoder decoder=new BASE64Decoder();
                String decode=new String(decoder.decodeBuffer(encode));
                System.out.println("decode: "+decode);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    

    bc实现主要是用Base64类的方法:

    public static void bouncybastleBase64(){
            byte[] encode = org.bouncycastle.util.encoders.Base64.encode(src.getBytes());
            System.out.println("encode: "+new String(encode));
            
            byte[] decode = org.bouncycastle.util.encoders.Base64.decode(encode);
            System.out.println("decode: "+new String(decode));
        }
    

    cc实现也是用Base64类,不过与bc的是不一样的,不同包中的类,只是名字一样:

    public static void commonscodecBase64(){
            byte[] encode=Base64.encodeBase64(src.getBytes());
            System.out.println("encode: "+new String(encode));  //需要转化为String
            
            byte[] decode = Base64.decodeBase64(encode);
            System.out.println("decode: "+new String(decode));
        }
    
    摘要算法

    摘要算法主要分为MD,SHA和Hmac算法,摘要算法其实是用于效验数据完整性的,我们在下载某些文件时,会有MD5和SHA1值提供我们效验下载的文件是否完整,可以用于根据数据生成其唯一的摘要值,无法根据摘要值知道原数据,属于不可逆的

    MD:

    在这里插入图片描述

    加密数据:

    private static String src="Hello MD";
    

    导入的类:

    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.security.Provider;
    import java.security.Security;
    
    import org.apache.commons.codec.binary.Hex;
    import org.apache.commons.codec.digest.DigestUtils;
    import org.bouncycastle.crypto.Digest;
    import org.bouncycastle.crypto.digests.MD2Digest;
    import org.bouncycastle.crypto.digests.MD4Digest;
    import org.bouncycastle.crypto.digests.MD5Digest;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    

    JDK有MD2和MD5的实现,使用的是MessageDigest类,而没有MD4的实现:

    public static void jdkMD5(){
            try {
                MessageDigest md=MessageDigest.getInstance("MD5");
                byte[] digest = md.digest(src.getBytes());
                System.out.println("JDK MD5: "+Hex.encodeHexString(digest));           //使用的是cc中带的Hex需要转换为十六进制
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            
        }
        
        public static void jdkMD2(){
            try {
                MessageDigest md=MessageDigest.getInstance("MD2");
                byte[] digest = md.digest(src.getBytes());
                System.out.println("JDK MD2: "+Hex.encodeHexString(digest));   
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            
        }
    

    而bc这三种都有,使用的是Digest 类:

    public static void bcMD4(){
            //方式一
    //        Digest digest=new MD4Digest();
    //        digest.update(src.getBytes(), 0, src.getBytes().length);
    //        byte[] md4Bytes=new byte[digest.getDigestSize()];
    //        digest.doFinal(md4Bytes, 0);
    //        System.out.println("BC MD4: "+org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
            
            
          //方式二(通过添加provider的方式,将sun的改为bc的provider)
            try {
                Security.addProvider(new BouncyCastleProvider());  //通过添加provider的方式
                MessageDigest md=MessageDigest.getInstance("MD4");
                byte[] digest = md.digest(src.getBytes());
                System.out.println("BC MD4: "+Hex.encodeHexString(digest));
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
        
        public static void bcMD5(){
            Digest digest=new MD5Digest();
            digest.update(src.getBytes(), 0, src.getBytes().length);
            byte[] md4Bytes=new byte[digest.getDigestSize()];
            digest.doFinal(md4Bytes, 0);
            System.out.println("BC MD5: "+org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
        }
        
        public static void bcMD2(){
            Digest digest=new MD2Digest();
            digest.update(src.getBytes(), 0, src.getBytes().length);
            byte[] md4Bytes=new byte[digest.getDigestSize()];
            digest.doFinal(md4Bytes, 0);
            System.out.println("BC MD2: "+org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
        }
    

    cc和JDK是一样的,毕竟是对JDK加密的简化,直接使用DigestUtils中的方法,很简单,而且前两种方法还需要将MD值转换为十六进制,cc直接就帮我们转了:

    public static void ccMD2(){        //有方法直接就可以转换十六进制
            System.out.println("CC MD2: "+DigestUtils.md2Hex(src.getBytes()));
        }
        
        public static void ccMd5(){
            System.out.println("CC MD5: "+DigestUtils.md5Hex(src.getBytes()));
        }
    
    SHA:

    这里只是使用SHA-1,其他类型类似
    在这里插入图片描述

    加密数据:

    private static String src="Hello SHA";
    

    要导入的类:

    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    import org.apache.commons.codec.binary.Hex;
    import org.apache.commons.codec.digest.DigestUtils;
    import org.bouncycastle.crypto.Digest;
    import org.bouncycastle.crypto.digests.SHA1Digest;import sun.security.provider.SHA;
    

    JDK实现方式(同样是使用MessageDigest):

    public static void jdkSHA1(){
            MessageDigest digest;
            try {
                digest = MessageDigest.getInstance("SHA");
                digest.update(src.getBytes());
                System.out.println("JDK SHA1: "+Hex.encodeHexString(digest.digest()));
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
    

    bc的实现方式(同样是Digest 类):

    public static void mcSHA1(){
            Digest digest=new SHA1Digest();
            digest.update(src.getBytes(),0,src.getBytes().length);
            byte[] sha1Byte1=new byte[digest.getDigestSize()];
            digest.doFinal(sha1Byte1, 0);
            System.out.println("MC SHA1:"+org.bouncycastle.util.encoders.Hex.toHexString(sha1Byte1));
        }
    

    cc的实现方式:

        public static void ccsha(){
            System.out.println("CC sha1:"+DigestUtils.sha1Hex(src));
        }
    
    Hmac(含有密钥的摘要算法,也有简称mac,密钥不同摘要也不同):

    在这里插入图片描述
    要加密的数据:

    private static String src="Hello HMAC";
    

    要导入的类:

    import javax.crypto.KeyGenerator;
    import javax.crypto.Mac;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    import org.apache.commons.codec.binary.Hex;
    import org.bouncycastle.crypto.digests.MD5Digest;
    import org.bouncycastle.crypto.macs.HMac;
    import org.bouncycastle.crypto.params.KeyParameter;
    

    JDK的实现方式:

    public static void jdkHmacMD5(){
            try {
                KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD5");  //初始化KeyGenerator
                SecretKey secretKey=keyGenerator.generateKey(); //产生密钥
                //byte[] key=secretKey.getEncoded();     //获得密钥(默认生成)
                
                byte[] key=Hex.decodeHex(new char[]{'a','a','a','a','a','a','a','a','a','a'});  //手动生成密钥(十位)
                
                SecretKey secretKey2=new SecretKeySpec(key, "HmacMD5"); //还原密钥
                Mac mac=Mac.getInstance(secretKey2.getAlgorithm());  //实例化mac
                //初始化mac
                mac.init(secretKey2);
                byte[] hmacMD5Bytes=mac.doFinal(src.getBytes());
                System.out.println("jdk hmacMD5: "+Hex.encodeHexString(hmacMD5Bytes));
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
    

    bc的实现方式:

    public static void bcHmacMd5(){
            HMac hMac=new HMac(new MD5Digest());
            hMac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex.decode("aaaaaaaaaa")));  //需要十位密钥
            hMac.update(src.getBytes(),0,src.getBytes().length);
            
            byte[] hmacMD5=new byte[hMac.getMacSize()];
            hMac.doFinal(hmacMD5, 0);
            System.out.println("bc hmacMD5: "+org.bouncycastle.util.encoders.Hex.toHexString(hmacMD5));
    
        }
    
    对称加密算法

    严格意义上的加密算法,分为对称和非对称加密算法,所谓对称是说发送方和接收方的密钥是一样的,而非对称我们后面再说。因为密钥一样所以安全性跟非对称比较来说就不太安全了

    对称加密算法主要分为:DES , 3DES(3重DES) , AES(想要替代DES) , PBE(基于口令的对称算法)

    DES:

    在这里插入图片描述
    加密数据 :

    private static String src="Hello DES";
    

    导入的类:

    import java.security.Security;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    
    import org.apache.commons.codec.binary.Hex;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    

    JDK的实现方式:

    public static void jdkDES(){
            try {
                //生成key
                KeyGenerator keyGenerator=KeyGenerator.getInstance("DES");
                keyGenerator.init(56);      //指定key长度,同时也是密钥长度(56位)
                SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
                byte[] key = secretKey.getEncoded();  //生成key
                
                //key转换成密钥
                DESKeySpec desKeySpec=new DESKeySpec(key);
                SecretKeyFactory factory=SecretKeyFactory.getInstance("DES");
                SecretKey key2 = factory.generateSecret(desKeySpec);      //转换后的密钥
                
                //加密
                Cipher cipher=Cipher.getInstance("DES/ECB/PKCS5Padding");  //算法类型/工作方式/填充方式
                cipher.init(Cipher.ENCRYPT_MODE, key2);   //指定为加密模式
                byte[] result=cipher.doFinal(src.getBytes());
                System.out.println("jdkDES加密: "+Hex.encodeHexString(result));  //转换为十六进制
                
                //解密
                cipher.init(Cipher.DECRYPT_MODE,key2);  //相同密钥,指定为解密模式
                result = cipher.doFinal(result);   //根据加密内容解密
                System.out.println("jdkDES解密: "+new String(result));  //转换字符串
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    bc的实现方式,为了和JDK的实现方式一致(不想记太多类),采用了添加provider的方式 :

    public static void bcDES(){
            try {
                //通过改变provider的方式
                Security.addProvider(new BouncyCastleProvider());
                
                //生成key,使用bc需要在后面指定"BC"
                KeyGenerator keyGenerator=KeyGenerator.getInstance("DES","BC");
                
                keyGenerator.getProvider();
                
                keyGenerator.init(56);      //指定key长度,同时也是密钥长度
                SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
                byte[] key = secretKey.getEncoded();  //生成key
                
                //key转换成密钥
                DESKeySpec desKeySpec=new DESKeySpec(key);
                SecretKeyFactory factory=SecretKeyFactory.getInstance("DES");
                SecretKey key2 = factory.generateSecret(desKeySpec);      //转换后的密钥
                
                //加密
                Cipher cipher=Cipher.getInstance("DES/ECB/PKCS5Padding");  //算法类型/工作方式/填充方式
                cipher.init(Cipher.ENCRYPT_MODE, key2);
                byte[] result=cipher.doFinal(src.getBytes());
                System.out.println("bcDES加密: "+Hex.encodeHexString(result));  //转换为十六进制
                
                //解密
                cipher.init(Cipher.DECRYPT_MODE,key2);  //相同密钥
                result = cipher.doFinal(result);   //根据加密内容解密
                System.out.println("bcDES解密: "+new String(result));  //转换字符串
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    就是记得添加bc的provider,和KeyGenerator.getInstance的参数(“DES”,“BC”)

    3DES(使用DESede作为标识):

    在这里插入图片描述
    要加密的数据:

    private static String src="Hello 3DES";
    

    导入的类:

    import java.security.SecureRandom;
    import java.security.Security;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESedeKeySpec;
    
    import org.apache.commons.codec.binary.Hex;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    

    JDK的实现方法:

    public static void jdkDES(){
            try {
                //生成key
                KeyGenerator keyGenerator=KeyGenerator.getInstance("DESede");
                //keyGenerator.init(112);      //3DES需要112 or 168位
                keyGenerator.init(new SecureRandom());   //或者使用这种方式默认长度,无需指定长度
                SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
                byte[] key = secretKey.getEncoded();  //生成key
                
                //key转换成密钥
                DESedeKeySpec desKeySpec=new DESedeKeySpec(key);
                SecretKeyFactory factory=SecretKeyFactory.getInstance("DESede");
                SecretKey key2 = factory.generateSecret(desKeySpec);      //转换后的密钥
                
                //加密
                Cipher cipher=Cipher.getInstance("DESede/ECB/PKCS5Padding");  //算法类型/工作方式/填充方式
                cipher.init(Cipher.ENCRYPT_MODE, key2);   //指定为加密模式
                byte[] result=cipher.doFinal(src.getBytes());
                System.out.println("jdk3DES加密: "+Hex.encodeHexString(result));  //转换为十六进制
                
                //解密
                cipher.init(Cipher.DECRYPT_MODE,key2);  //相同密钥,指定为解密模式
                result = cipher.doFinal(result);   //根据加密内容解密
                System.out.println("jdk3DES解密: "+new String(result));  //转换字符串
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    bc的实现方式:

    public static void bcDES(){
            try {
                //通过改变provider的方式,其他操作一样
                Security.addProvider(new BouncyCastleProvider());
                
                //生成key
                KeyGenerator keyGenerator=KeyGenerator.getInstance("DESede");
                keyGenerator.init(new SecureRandom());
                SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
                byte[] key = secretKey.getEncoded();  //生成key
                
                //key转换成密钥
                DESedeKeySpec desKeySpec=new DESedeKeySpec(key);
                SecretKeyFactory factory=SecretKeyFactory.getInstance("DESede");
                SecretKey key2 = factory.generateSecret(desKeySpec);      //转换后的密钥
                
                //加密
                Cipher cipher=Cipher.getInstance("DESede/ECB/PKCS5Padding");  //算法类型/工作方式/填充方式
                cipher.init(Cipher.ENCRYPT_MODE, key2);   //指定为加密模式
                byte[] result=cipher.doFinal(src.getBytes());
                System.out.println("jdk3DES加密: "+Hex.encodeHexString(result));  //转换为十六进制
                
                //解密
                cipher.init(Cipher.DECRYPT_MODE,key2);  //相同密钥,指定为解密模式
                result = cipher.doFinal(result);   //根据加密内容解密
                System.out.println("jdk3DES解密: "+new String(result));  //转换字符串
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    AES:

    在这里插入图片描述
    基本实现和DES类似,只不过在实现该算法的时候,设置密钥长度大于128会出现错误:Illegal key size or default parameters,这是因为美国的出口限制,Sun通过权限文件(local_policy.jar、US_export_policy.jar)做了相应限制,Oracle在其官方网站上提供了无政策限制权限文件(Unlimited Strength Jurisdiction Policy Files),我们只需要将其部署在JRE环境中,就可以解决限制问题

    JDK8的无政策限制权限文件(http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html)

    将下载的local_policy.jar和US_export_policy.jar替换JDK的JRE环境中,或者是JRE环境中上述两个jar文件即可

    非对称的ELGamal加密算法算法也有该问题,解决方法相同

    加密的数据:

    private static String src="Hello AES";
    

    导入的类:

    import java.security.Key;
    import java.security.SecureRandom;
    import java.security.Security;
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import org.apache.commons.codec.binary.Hex;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    

    JDK的实现:

    public static void jdkAES(){
            try {
                //生成key
                KeyGenerator keyGenerator=KeyGenerator.getInstance("AES");
                keyGenerator.init(new SecureRandom());
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] key1 = secretKey.getEncoded();
                
                //key转换为密钥
                Key key2 = new SecretKeySpec(key1, "AES");
                
                //加密
                Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5padding");
                cipher.init(Cipher.ENCRYPT_MODE, key2);
                byte[] result = cipher.doFinal(src.getBytes());
                System.out.println("jdkAES加密: "+Hex.encodeHexString(result));  //转换为十六进制
                
                //解密
                cipher.init(Cipher.DECRYPT_MODE, key2);
                result = cipher.doFinal(result);
                System.out.println("jdkAES解密: "+new String(result));  //转换字符串
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    bc的实现(同样使用了添加provider的做法):

    public static void bcAES(){
            try {
                Security.addProvider(new BouncyCastleProvider());
                
                //生成key
                KeyGenerator keyGenerator=KeyGenerator.getInstance("AES", "BC");
                keyGenerator.getProvider();
                keyGenerator.init(128);      //显示指定密钥长度
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] key1 = secretKey.getEncoded();
                
                //key转换为密钥
                Key key2 = new SecretKeySpec(key1, "AES");
                
                //加密
                Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5padding");
                cipher.init(Cipher.ENCRYPT_MODE, key2);
                byte[] result = cipher.doFinal(src.getBytes());
                System.out.println("jdkAES加密: "+Hex.encodeHexString(result));  //转换为十六进制
                
                //解密
                cipher.init(Cipher.DECRYPT_MODE, key2);
                result = cipher.doFinal(result);
                System.out.println("jdkAES解密: "+new String(result));  //转换字符串
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    PBE:

    基于口令的对称加密算法(它其实是对之前的算法的包装,比如说MD5和DES,我这里就是的是对MD5和DES包装的PBE算法,还有其他类型的PBE),口令就是我们俗话说的密码,PBE中有一个salt(盐)的概念,盐就是干扰码

    加密的数据:

    private static String src="Hello PBE";
    

    导入的类:

    import java.security.Key;
    import java.security.SecureRandom;
    
    import javax.crypto.Cipher;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.PBEKeySpec;
    import javax.crypto.spec.PBEParameterSpec;
    import org.apache.commons.codec.binary.Base64;
    

    JDk的实现:

    public static void jdkPBE(){
            try {
                //初始化盐
                SecureRandom random=new SecureRandom();
                byte[] salt = random.generateSeed(8);   //指定为8位的盐 (盐就是干扰码,通过添加干扰码增加安全)
                
                //口令和密钥
                String password="lynu";              //口令
                PBEKeySpec pbeKeySpec=new PBEKeySpec(password.toCharArray());
                SecretKeyFactory factory=SecretKeyFactory.getInstance("PBEWITHMD5andDES");
                Key key=factory.generateSecret(pbeKeySpec);  //密钥
                
                //加密
                PBEParameterSpec pbeParameterSpec=new PBEParameterSpec(salt, 100);   //参数规范,第一个参数是盐,第二个是迭代次数(经过散列函数多次迭代)
                Cipher cipher=Cipher.getInstance("PBEWITHMD5andDES");
                cipher.init(Cipher.ENCRYPT_MODE, key,pbeParameterSpec);
                byte[] result = cipher.doFinal(src.getBytes());
                System.out.println("jdk PBE加密: "+Base64.encodeBase64String(result));
                
                
                //解密
                cipher.init(Cipher.DECRYPT_MODE, key,pbeParameterSpec);
                result = cipher.doFinal(result);
                System.out.println("jdk PBE解密: "+new String(result));
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            
        }
    
    非对称的算法:

    非对称算法就是发送方和接收方的密钥是不一样的,非对称相对于对称来说,有公钥和私钥的概念,基本上公钥是公开的,比如会在网络上传输,而私钥安全性要求就要高很多了,因为私钥是要保密的

    基本的非对称算法有DH,RSA,ELGamal算法

    DH:

    基于交换交换的非对称算法,接收方需要得到接收方的key构建本地密钥,而接收方也需要得到发送方的key构建自己本地的密钥。只有JDK的实现
    在这里插入图片描述
    需要加密的数据:

    private static String src="Hello DH";
    

    需要导入的类:

    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Objects;
    import javax.crypto.Cipher;
    import javax.crypto.KeyAgreement;
    import javax.crypto.SecretKey;
    import javax.crypto.interfaces.DHPublicKey;
    import javax.crypto.spec.DHParameterSpec;
    

    JDK的实现:

    public static void jdkDH(){
            try {
                //初始化发送方密钥
                KeyPairGenerator senderKeyPairGenerator=KeyPairGenerator.getInstance("DH");
                senderKeyPairGenerator.initialize(512);   //密钥长度
                KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
                byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();  //发送方key,需传递给接收方(网络,文件)
                
                //初始化接收方密钥
                KeyFactory factory=KeyFactory.getInstance("DH");
                X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(senderPublicKeyEnc);  //根据从发送方得到的key解析
                PublicKey receiverPublicKey=factory.generatePublic(x509EncodedKeySpec);
                DHParameterSpec dhParameterSpec=((DHPublicKey)receiverPublicKey).getParams();
                KeyPairGenerator receiverKeyPairGenerator=KeyPairGenerator.getInstance("DH");
                receiverKeyPairGenerator.initialize(dhParameterSpec);
                KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
                PrivateKey receiverPrivateKey = receiverKeyPair.getPrivate();
                byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded();
                
                //密钥构建
                KeyAgreement receiverKeyAgreement=KeyAgreement.getInstance("DH");
                receiverKeyAgreement.init(receiverPrivateKey);
                receiverKeyAgreement.doPhase(receiverPublicKey, true);
                SecretKey receiverDESKey=receiverKeyAgreement.generateSecret("DES");  //发送发密钥(公钥)
                KeyFactory senderKeyFactory=KeyFactory.getInstance("DH");
                x509EncodedKeySpec=new X509EncodedKeySpec(receiverPublicKeyEnc);
                PublicKey senderPublicKey=senderKeyFactory.generatePublic(x509EncodedKeySpec);
                KeyAgreement senderKeyAgreement=KeyAgreement.getInstance("DH");
                senderKeyAgreement.init(senderKeyPair.getPrivate());
                senderKeyAgreement.doPhase(senderPublicKey, true);
                SecretKey senderDESKey=senderKeyAgreement.generateSecret("DES");        //接收方密钥(私钥)
                if(Objects.equals(receiverDESKey, senderDESKey)){
                    System.out.println("双方密钥相同");
                }
                //加密
                Cipher cipher=Cipher.getInstance("DES");
                cipher.init(Cipher.ENCRYPT_MODE, senderDESKey);
                byte[] result = cipher.doFinal(src.getBytes());
                System.out.println("jdk DH加密: "+org.apache.commons.codec.binary.Base64.encodeBase64String(result));
                
                //解密            
                cipher.init(Cipher.DECRYPT_MODE, receiverDESKey);
                result=cipher.doFinal(result);
                System.out.println("jdk DH解密: "+new String(result));
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
    RSA:

    RSA相较于DH算法的实现简单,适用范围较广,公钥和私钥的创建较简单,而且支持公钥加密,私钥解密或者是私钥加密,公钥解密两种方式

    要加密的数据:

    private static String src="Hello RSA";
    

    要导入的类:

    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import javax.crypto.Cipher;
    import org.apache.commons.codec.binary.Base64;
    

    JDK的实现,公钥加密,私钥解密和私钥加密,公钥解密两种方式:

    public static void jdkRSA(){
            try {
                KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
                keyPairGenerator.initialize(512);
                KeyPair keyPair = keyPairGenerator.generateKeyPair();
                RSAPublicKey rsaPublicKey=(RSAPublicKey) keyPair.getPublic();           //公钥
                RSAPrivateKey rsaPrivateKey=(RSAPrivateKey) keyPair.getPrivate();       //私钥
                System.out.println("public key:"+Base64.encodeBase64String(rsaPublicKey.getEncoded()));
                System.out.println("private key:"+Base64.encodeBase64String(rsaPrivateKey.getEncoded()));
                
                //私钥加密,公钥解密--加密
                PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
                KeyFactory keyFactory=KeyFactory.getInstance("RSA");
                PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
                Cipher cipher=Cipher.getInstance("RSA");
                cipher.init(Cipher.ENCRYPT_MODE, privateKey);
                byte[] result = cipher.doFinal(src.getBytes());
                System.out.println("RSA私钥加密,公钥解密--加密:"+Base64.encodeBase64String(result));
                
                //私钥加密,公钥解密--解密
                X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded());
                keyFactory=KeyFactory.getInstance("RSA");
                PublicKey publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
                cipher=Cipher.getInstance("RSA");
                cipher.init(Cipher.DECRYPT_MODE,publicKey);
                result = cipher.doFinal(result);
                System.out.println("RSA私钥加密,公钥解密--解密:"+new String(result));
                
                //公钥加密,私钥解密--加密
                x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded());
                keyFactory=KeyFactory.getInstance("RSA");
                publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
                cipher=Cipher.getInstance("RSA");
                cipher.init(Cipher.ENCRYPT_MODE,publicKey);
                result = cipher.doFinal(src.getBytes());
                System.out.println("RSA公钥加密,私钥解密--加密:"+Base64.encodeBase64String(result));
                
                //公钥加密,私钥解密--解密
                pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
                keyFactory=KeyFactory.getInstance("RSA");
                privateKey =keyFactory.generatePrivate(pkcs8EncodedKeySpec);
                cipher=Cipher.getInstance("RSA");
                cipher.init(Cipher.DECRYPT_MODE,privateKey);
                result=cipher.doFinal(result);
                System.out.println("RSA公钥加密,私钥解密--解密:"+new String(result));
                
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    ELGamal:

    ELGamal算法的和AES一样存在密钥长度的限制,解决方法和AES一致。不过ELGamal只支持公钥加密,私钥解密这种方式。只有bc的实现方式

    要加密的数据:

    private static String src="Hello ELGamal";
    

    导入的类:

    import java.security.AlgorithmParameterGenerator;
    import java.security.AlgorithmParameters;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.SecureRandom;
    import java.security.Security;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import javax.crypto.Cipher;
    import javax.crypto.spec.DHParameterSpec;
    import org.apache.commons.codec.binary.Base64;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    

    bc的实现方式:

    public static void bcELGamal(){
            try {
                //加载provider
                Security.addProvider(new BouncyCastleProvider());
                
                //初始化密钥
                AlgorithmParameterGenerator algorithmParameterGenerator=AlgorithmParameterGenerator.getInstance("ELGamal");
                algorithmParameterGenerator.init(256);
                AlgorithmParameters algorithmParameters=algorithmParameterGenerator.generateParameters();
                DHParameterSpec dhParameterSpec=(DHParameterSpec)algorithmParameters.getParameterSpec(DHParameterSpec.class);
                KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("ELGamal");
                keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());
                KeyPair keyPair=keyPairGenerator.generateKeyPair();
                PublicKey elGamalPublicKey=keyPair.getPublic();        //公钥
                PrivateKey elGamalPrivateKey=keyPair.getPrivate();     //私钥
                System.out.println("public key:"+Base64.encodeBase64String(elGamalPublicKey.getEncoded()));
                System.out.println("private key:"+Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));
                
                //公钥加密,私钥解密--加密
                X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
                KeyFactory keyFactory=KeyFactory.getInstance("ELGamal");
                PublicKey publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
                Cipher cipher=Cipher.getInstance("ELGamal");
                cipher.init(Cipher.ENCRYPT_MODE,publicKey);
                byte[] result = cipher.doFinal(src.getBytes());
                System.out.println("ELGamal加密:"+Base64.encodeBase64String(result));
                
                //公钥加密,私钥解密--解密
                PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
                keyFactory=KeyFactory.getInstance("ELGamal");
                PrivateKey privateKey =keyFactory.generatePrivate(pkcs8EncodedKeySpec);
                cipher=Cipher.getInstance("ELGamal");
                cipher.init(Cipher.DECRYPT_MODE,privateKey);
                result=cipher.doFinal(result);
                System.out.println("ElGamal解密:"+new String(result));
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            
        }
    

    作者:OverZeal
    出处:https://www.cnblogs.com/lz2017/p/6917049.html
    本站使用「署名 4.0 国际」创作共享协议,转载请在文章明显位置注明作者及出处。

    展开全文
  • 对称加密非对称加密不可逆加密算法 根据密钥类型不同可以将现代密码技术分为两类:对称加密算法(私钥密码体系)和非对称加密算法(公钥密码体系)。 1对称加密算法 原理 对称加密算法中,数据加密和解密采用的都是...

    对称加密 非对称加密 不可逆加密算法

    根据密钥类型不同可以将现代密码技术分为两类:对称加密算法(私钥密码体系)和非对称加密算法(公钥密码体系)。

    1 对称加密算法

    原理

    对称加密算法中,数据加密和解密采用的都是同一个密钥,因而其安全性依赖于所持有密钥的安全性。

    优点

    加密和解密速度快,加密强度高,且算法公开.

    缺点

    实现密钥的秘密分发困难,在大量用户的情况下密钥管理复杂,而且无法完成身份认证等功能,不便于应用在网络开放的环境中。

    特点

    算法公开、计算量小、加密速度快、加密效率高。

    著名算法

    目前最著名的对称加密算法有数据加密标准DES,但传统的DES由于只有56位的密钥,因此已经不适应当今分布式开放网络对数据加密安全性的要求。欧洲数据加密标准IDEA等,目前加密强度最高的对称加密算法是高级加密标准AES,AES提供128位密钥,128位AES的加密强度是56位DES加密强度的1021倍还多。。

    过程

    对称加密算法过程是将数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。

    不足之处是,交易双方都使用同样钥匙,安全性得不到保证。假设两个用户需要使用对称加密方法加密然后交换数据,则用户最少需要2个密钥并交换使用,如果企业内用户有n个,则整个企业共需要n×(n-1) 个密钥。

     

    2 非对称加密算法

    原理

    非对称加密算法使用两把完全不同但又是完全匹配的一对钥匙(即一把公开密钥或加密密钥和专用密钥或解密密钥)—公钥和私钥。在使用不对称加密算法加密文件时,只有使用匹配的一对公钥和私钥,才能完成对明文的加密和解密过程。加密明文时采用公钥加密,解密密文时使用私钥才能完成,而且发信方(加密者)知道收信方的公钥,只有收信方(解密者)才是唯一知道自己私钥的人。非对称加密算法的基本原理是,如果发信方想发送只有收信方才能解读的加密信息,发信方必须首先知道收信方的公钥,然后利用收信方的公钥来加密原文;收信方收到加密密文后,使用自己的私钥才能解密密文。

    优点

    非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。

    加密和解密花费时间长、速度慢,它不适合于对文件加密而只适用于对少量数据进行加密。

     

    著名算法

     

    广泛应用的非对称加密算法有RSA算法和美国国家标准局提出的DSA。

     

    3 不可逆加密算法

    原理

         不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。显然,在这类加密过程中,加密是自己,解密还得是自己,而所谓解密,实际上就是重新加一次密,所应用的“密码”也就是输入的明文。

    优点

    不可逆加密算法不存在密钥保管和分发问题,非常适合在分布式网络系统上使用。

    因加密计算复杂,工作量相当繁重,通常只在数据量有限的情形下使用,如广泛应用在计算机系统中的口令加密,利用的就是不可逆加密算法。近年来,随着计算机系统性能的不断提高,不可逆加密的应用领域正在逐渐增大。

    著名算法

    在计算机网络中应用较多不可逆加密算法的有RSA公司发明的MD5算法和由美国国家标准局建议的不可逆加密标准SHS(Secure Hash Standard:安全杂乱信息标准)等。

     

    注:

    对称加密算法、非对称加密算法和不可逆加密算法可以分别应用于数据加密、身份认证和数据安全传输。

    展开全文
  • Java 加密解密基础

    2016-05-27 23:20:51
    Java 加密解密基础 Java byte数组与十六进制字符串互转 Java BASE64加密解密 Java 加密解密之消息摘要算法(MD5 SHA MAC) Java 加密解密之对称加密算法DES Java 加密解密之对称加密算法DESede Java 加密解密...

    Java加密解密系列

    Java 加密解密基础
    Java byte数组与十六进制字符串互转
    Java BASE64加密解密
    Java 加密解密之消息摘要算法(MD5 SHA MAC)
    Java 加密解密之对称加密算法DES
    Java 加密解密之对称加密算法DESede
    Java 加密解密之对称加密算法AES
    Java 加密解密之对称加密算法PBE

    Java 加密解密基础

    密码学是研究编制密码和破译密码的技术科学。研究密码变化的客观规律,应用于编制密码以保守通信秘密的,称为编码学;应用于破译密码以获取通信情报的,称为破译学,总称密码学。

    密码学常用术语

    明文: 待加密数据。
    密文: 明文经过加密后数据。
    加密: 将明文转换为密文的过程。
    加密算法: 将明文转换为密文的转换算法。
    加密密钥: 通过加密算法进行加密操作的密钥。
    解密: 将密文转换为铭文的过程。
    解密算法: 将密文转换为明文的转换算法。
    解密密钥: 通过解密短发进行解密操作的密钥。

    密码学分类

    1. 按时间分
      • 古典密码:以字符为基本加密单元。
      • 现代密码:以信息块为基本加密单元。
    2. 按保密内容的算法划分
      • 受限制算法:算法的保密性基于保持算法的秘密。
      • 基于密钥算法:算法的保密性基于对密钥的保密。
    3. 按密钥体制划分
      • 对称密码体制:也叫单钥或私钥密码体制,加密过程与解密过程使用同一套密钥。对应的算法就是对称加密算法,例如 DES , AES 。
      • 非对称密码体制:也叫双钥或公钥密码体制,加密过程与解密过程使用不同的密钥。对应的算法就是非对称加密算法,例如 RSA 。
    4. 按明文处理方式划分

      • 流密码:也称为序列密码,加密时每次加密一位或者一个字节的明文。例如 RC4 算法。
      • 分组密码:加密时将明文分成固定长度的组,用同一个密钥和算法对每一组进行加密输出也是固定长度的明文。当最后一组大小不满足指定的分组大小时,
        有两种处理模式:

        • 无填充模式,直接对剩余数据进行加密,此组加密后大小与剩余数据有关;
        • 有填充模式,对于不满足指定长度分组的进行数据填充;如果恰巧最后一组数据与指定分组大小相同,那么直接添加一个指定大小的分组;填充的最后一个字节记录了填充的字节数。

    分组密码工作模式简介

    1. 电子密码本模–ECB
      将明文的各个分组独立的使用相同的密钥进行加密,这种方式加密时各分组的加密独立进行互不干涉,因而可并行进行。同样因为各分组独立加密的缘故,相同的明文分组加密之后具有相同的密文。该模式容易暴露明文分组的统计规律和结构特征。不能防范替换攻击。
      其实照实现来看, ECB 的过程只是把明文进行分组,然后分别加密,最后串在一起的过程。当消息长度超过一个分组时,不建议使用该模式。在每个分组中增加随机位 ( 如 128 位分组中 96 位为有效明文, 32 位的随机数 ) 则可稍微提高其安全性 , 但这样无疑造成了加密过程中数据的扩张。
      优点 :

      • 简单;
      • 有利于并行计算;
      • 误差不会被传送;

      缺点 :

      • 不能隐藏明文的模式;
      • 可能对明文进行主动攻击;
    2. 密码分组链接模 – CBC

      需要一个初始化向量 IV ,第一组明文与初始化向量进行异或运算后再加密,以后的每组明文都与前一组的密文进行异或运算后再加密。 IV 不需要保密,它可以明文形式与密文一起传送。
      优点:

      • 不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。

      缺点:

      • 不利于并行计算;
      • 误差传递;
      • 需要初始化向量IV
    3. 密文反馈模式–CFB

      需要一个初始化向量IV ,加密后与第一个分组明文进行异或运算产生第一组密文,然后对第一组密文加密后再与第二组明文进行异或运算缠身第二组密文,一次类推,直到加密完毕。
      优点:

      • 隐藏了明文模式;
      • 分组密码转化为流模式;
      • 可以及时加密传送小于分组的数据;

      缺点 :

      • 不利于并行计算;
      • 误差传送:一个明文单元损坏影响多个单元;
      • 唯一的IV;
    4. 输出反馈模式–OFB

      需要一个初始化向量IV ,加密后得到第一次加密数据,此加密数据与第一个分组明文进行异或运算产生第一组密文,然后对第一次加密数据进行第二次加密,得到第二次加密数据,第二次加密数据再与第二组明文进行异或运算产生第二组密文,一次类推,直到加密完毕。
      优点 :

      • 隐藏了明文模式;
      • 分组密码转化为流模式;
      • 可以及时加密传送小于分组的数据;

      缺点 :

      • 不利于并行计算;
      • 对明文的主动攻击是可能的 ;
      • 误差传送:一个明文单元损坏影响多个单元 ;
    5. 计数器模式–CTR

      使用计数器,计数器初始值加密后与第一组明文进行异或运算产生第一组密文,
      计数器增加,然后,加密后与下一组明文进行异或运算产生下一组密文,以此类推,直到加密完毕
      优点 :

      • 可并行计算 ;
      • 安全性至少与CBC 模式一样好 ;
      • 加密与解仅涉及密码算法的加密 ;

      缺点 :

      • 没有错误传播,不易确保数据完整性 ;
    6. 分组密码填充方式简介

      • PKCS5 :
        填充字符串由一个值为 5 的字节序列组成,每个字节填充该字节序列的长度。 明确定义 Block 的大小是 8 位
      • PKCS7 :
        填充字符串由一个值为 7 的字节序列组成,每个字节填充该字节序列的长度。 对于块的大小是不确定的,可以在 1-255 之间
      • ISO10126:
        填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节填充随机数据。
    展开全文
  • Java 加密解密之对称加密算法DES

    千次阅读 2016-05-27 23:31:12
    博客分类: Java Javajava des Java 加密解密基础 Java byte数组与十六进制字符串互转 Java BASE64加密解密 Java 加密解密之消息摘要算法(MD5 SHA MAC) ...Java 加密解密之对称加密算法PBEJava 加
  • Java加密-对称加密算法

    千次阅读 2016-12-12 10:00:46
    本位内容来自JAVA实现对称加密Java加密-对称加密算法对称加密算法是加密密钥等于解密密钥。常见的对称加密算法有: DES,3DES AES PBE IDEA DESDES(Data Encryption Standard)数据加密标准jdk方式实现DES的加解密...
  • Java 加密解密之对称加密算法DESede

    千次阅读 2016-05-27 23:33:06
    Java 加密解密基础 Java byte数组与十六进制字符串互转 Java BASE64加密解密 Java 加密解密之消息摘要算法(MD5 SHA MAC) Java 加密解密之对称加密算法DES Java 加密解密之对称加密算法DESede Java 加密解密...
  • Java 加密解密之对称加密算法AES

    千次阅读 2016-05-27 23:35:44
    Java 加密解密基础 Java byte数组与十六进制字符串互转 Java BASE64加密解密 Java 加密解密之消息摘要算法(MD5 SHA MAC) Java 加密解密之对称加密算法DES Java 加密解密之对称加密算法DESede Java 加密解密...
  • Java加密体系-java.security包

    千次阅读 2020-05-01 11:48:40
    JCA(Java Cryptography Architecture) 是Java体系结构,提供了基本Java加密框架,比如证书、数字签名、消息摘要、秘钥对生成器等,在java.security包中实现。 JCE(Java Cryptography Extension)是JCA的扩展,...
  • Java加密解密算法-SHA加密

    千次阅读 2016-07-21 20:08:35
    Java加密解密算法-SHA加密
  • java加密解密研究

    2014-07-19 15:25:54
    java加密解密研究2、Bouncy Castle和Commons Codec加密组件 java加密解密研究3、Base64算法 java加密解密研究4、UrlBase64算法 java加密解密研究5、消息摘要算法简介 java加密解密研究6...
  • Java加密体系:java.security包

    千次阅读 2018-09-29 23:21:49
    JCA(Java Cryptography Architecture) 是Java体系结构,提供了基本Java加密框架,比如证书、数字签名、消息摘要、秘钥对生成器等,在java.security包中实现。 JCE(Java Cryptography Extension)是JCA的扩展,主要...
  • java加密算法介绍

    2013-09-05 09:30:53
    java加密解密研究1、密码学的基本分类 ...java加密解密研究2、Bouncy Castle和Commons Codec加密组件 java加密解密研究3、Base64算法 java加密解密研究4、UrlBase64算法 java加密解密研究5、消息摘要算法简介
  • Java加密解密入门

    千次阅读 2015-04-17 22:25:25
    Java加密解密概述 Java安全领域分为四个部分:JCA-Java加密体系结构;JCE-Java加密扩展包;JSSE-Java安全套接字扩展包;JAAS-Java鉴别与安全服务。 JCA提供基本的加密框架,如证书、数字签名、消息摘要和密钥对...
  • Java加密技术——对称加密算法一览

    千次阅读 2016-05-21 16:57:25
    Java加密技术(二)——对称加密算法  Java对称加密算法,最常用的莫过于DES数据加密算法。  DES  Data Encryption Standard,即数据加密算法。是IBM公司于1975年研究成功并公开发表的。DES算法的入口参数有三...
  • 1、javax.crypto.Cipher 类提供加密和解密的功能,它构成了Java加密扩展(JCE)框架的核心。 2、Cipher 的 getInstance(String transformation) 方法可以获取实例,参数 transformation 表示转换名称,包括:加密...
  • Java加密解密代码小记

    千次阅读 2018-01-26 11:18:21
    花了一周时间看了一本叫《Java加密与解密的艺术》的书,这本书还是可以看看,第三章是对java API中类的一些说明,以及一些小列子,4~9章是对这些类的详细代码表述,我都是随便扫了一眼看了一下,第10~12是关于加密...
  • JAVA加密或混淆技术总结

    千次阅读 2018-10-19 12:33:29
    JAVA加密或混淆技术较多,下面以Allatori为例进行介绍。  一、 混淆器介绍  1、混淆出现的背景   Java是一种跨平台的、解释型语言,Java源代码编译成中间“字节码”存储于class文件中。由于跨平台的需要,Java...
  • Java Security:Java加密框架(JCA)简要说明  加密服务总是关联到一个特定的算法或类型,它既提供了密码操作(如Digital Signature或MessageDigest),生成或供应所需的加密材料(Key或Parameters)加密操作,...
  • JAVA加密C++解密简单方法

    千次阅读 2015-11-16 16:10:25
    java加密C++解密:【key可以随机生成】需要KEY需要一样(如果需要更为复杂的加密可以在加密器初始化是传入一个盐值,具体实现方法可以网上搜很多),java加密的填充方式 和C++解密填充方式要一样,其中加密解密返回...
  • 博客分类: Java Javajava md5java shajava mac Java 加密解密基础 Java byte数组与十六...Java 加密解密之对称加密算法DES Java 加密解密之对称加密算法DESede Java 加密解密之对称加密算法AES Java 加密解密
  • Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC  Java加密技术(二)——对称加密DES&AES  Java加密技术(三)——PBE算法  Java加密技术(四)——非对称加密算法RSA  Java加密技术(五)——非...
  • Java 加密解密之对称加密算法PBE

    千次阅读 2012-03-27 22:57:29
    Java 加密解密之对称加密算法PBE PBE是一种基于口令的加密算法,使用口令代替其他对称加密算法中的密钥,其特点在于口令由用户自己掌管,不借助任何物理媒体;采用随机数(这里我们叫做盐)杂凑多重加密等方法...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 40,226
精华内容 16,090
关键字:

java加密

java 订阅