对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信性至关重要。

特点 

对称加密算法的特点是算法公开、计算量小、加密速度快、加密效率高。
不足之处是,交易双方都使用同样钥匙,安全性得不到保证。此外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。而与公开密钥加密算法比起来,对称加密算法能够提供加密和认证却缺乏了签名功能,使得使用范围有所缩小。在计算机专网系统中广泛使用的对称加密算法有DES和IDEA等
 
算法
DES算法3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法。
 
附上代码(生成密钥及加密、解密)
 
public static void desSecret() throws NoSuchAlgorithmException {

        // 密钥生成器
        KeyGenerator key = KeyGenerator.getInstance("DESede");
        /**
         * 初始化密钥生成器 该步骤一般指定密钥的长度。如果该步骤省略的话, 会根据算法自动使用默认的密钥长度。指定长度时,
         * 若第一步密钥生成器使用的是“DES”算法,则密钥长度必须是56位;
         * 若是“DESede”,则可以是112或168位,其中112位有效;若是“AES”, 可以是128,
         * 192或256位;若是“Blowfish”,则可以是32至448之间可以被8整除的数;
         * “HmacMD5”和“HmacSHA1”默认的密钥长度都是64个字节
         */
        key.init(168);
        // 生成密钥
        SecretKey secret = key.generateKey();
        FileOutputStream s;
        try {
            s = new FileOutputStream("D://des-pri.key");
            ObjectOutputStream st = new ObjectOutputStream(s);
            st.writeObject(secret);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static byte[] desEncrypt(String str) throws Exception {
        byte[] miby = null;
        FileInputStream s = new FileInputStream("D://des-pri.key");
        ObjectInputStream st = new ObjectInputStream(s);
        SecretKey secret = (SecretKey) st.readObject();
        // 工厂模式获取Cipher实例 密码器
        Cipher cp = Cipher.getInstance("DESede");
        // 初始化cipher ENCRYPT_MODE表示加密DECRYPT_MODE解密 后面一个参数是密钥
        cp.init(Cipher.ENCRYPT_MODE, secret);
        byte[] by = str.getBytes("utf-8");
        // 对字节码机密 miby就是加密后的字节码
        miby = cp.doFinal(by);
        return miby;
    }

    public static String desUnEncrypt(byte[] sct) throws Exception {
        // 通过提供的密钥文件 获取密钥对象 进行解密
        FileInputStream s = new FileInputStream("D://des-pri.key");
        ObjectInputStream st = new ObjectInputStream(s);
        SecretKey secret = (SecretKey) st.readObject();
        // 工厂模式获取Cipher实例 密码器
        Cipher cp = Cipher.getInstance("DESede");
        // 初始化cipher ENCRYPT_MODE表示加密DECRYPT_MODE解密 后面一个参数是密钥
        cp.init(Cipher.DECRYPT_MODE, secret);

        // 对密文字节码进行解密 如果密码写入文件可以使用文件流读写成一个数组
        byte[] miby = cp.doFinal(sct);
        // 获取密文字符串
        String minwen = new String(miby, "utf-8");
        return minwen;
    }

 

非对称加密:非对称加密算法需要两个密钥公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥

 

特点

非对称加密与对称加密相比,其安全性更好:对称加密的通信双方使用相同的秘钥,如果一方的秘钥遭泄露,那么整个通信就会被破解。而非对称加密使用一对秘钥,一个用来加密,一个用来解密,而且公钥是公开的,秘钥是自己保存的,不需要像对称加密那样在通信之前要先同步秘钥。
非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。
 
算法
RSAElgamal、Rabin、D-H、ECC
 
 
   工作的时候有对接银行接口,整理下关于RSA加密,双方通讯如何保证数据的安全 (RSA + 数字签名)
   
       一般通讯的双方交换对方公钥, 各方持有本方的公私钥、与对方的公钥  (私钥只有本人持有)
        通讯:
               定义报文格式 :  128签名+加密报文
               A通讯B
                   1. A用B的公钥加密明文,加密后的报文用A的私钥签名,组成报文发送B(报文约定格式)
        2. B根据约定的报文格式获取加密的密文与签名,通过B的私钥解密获取明文、A的公钥验证签名(加密数据)  
     
场景
 
  数字签名原理
  1. A通过使用B的公钥加密数据后发给B,B利用B的私钥解密就得到了需要的数据(进过B公钥加密的数据只有B的私钥能够  
  2.   * 解开,C没有B的私钥,所以C解不开,但C可以使用B的公钥加密一份数据发给B,这样一来,问题来了,B收到的数据到  
  3.   * 底是A发过来的还是C发过来的呢)  
  4.   * 由于私钥是唯一的,那么A就可以利用A自己的私钥进行加密,然后B再利用A的公钥来解密,就可以确定:一定是A的消息,数字签名的原理就基于此

     A想将目标数据传给B,此时A需要准备1和2两部分    

  1. A使用B的公钥将原始信息加密,以起到保密作用(只有B的私钥能解开,其他人使用其他钥匙都解不开,当然就保密咯)  
  2. A使用A的私钥将原始信息的摘要进行签名,以起到接收方B确定是A发过来的作用(A用A的私钥对目标数据的摘要进行签名,然后传给B,同时,C用C的私钥对任意信息进行签名也传给B,B想接受的是A的数据(比如说一个转帐请求),于是B 就通过A的公钥对接受到的两个信息进行解密,解开的就是A(A的公钥能且只能解开A的私钥加密的数据))
附上代码(生成非对称公私钥及加密、解密 + 数字签名)
 
  
 public static final String KEY_ALGORITHM = "RSA";  
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";  
  
    
    // 初始化RSA非对称密钥
    public static void generaterA() {
        try {
            KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
            SecureRandom secrand = new SecureRandom();
            keygen.initialize(1024, secrand);
            KeyPair keys = keygen.genKeyPair();
            PublicKey pubkey = keys.getPublic();
            PrivateKey prikey = keys.getPrivate();
            
            String strpk = new String(Base64.encodeBase64(pubkey.getEncoded()));  
            String strprivk = new String(Base64.encodeBase64(prikey.getEncoded()));
    
            DesSecretUtil.saveData(strpk.getBytes(), "D://rsa-pub_A.pem");
            DesSecretUtil.saveData(strprivk.getBytes(), "D://rsa-pri_A.pem");
            
        } catch (java.lang.Exception e) {
            System.out.println("生成密钥对失败");
            e.printStackTrace();
        }
    }  
    
    /** 
     * 用私钥对信息生成数字签名 
     *  
     * @param data 
     *            加密数据 
     * @param privateKey 
     *            私钥 
     *  
     * @return 
     * @throws Exception 
     */  
    
    public static String sign(byte[] data, String privateKey) throws Exception {  
        // 解密由base64编码的私钥  
        byte[] keyBytes = Base64.decodeBase64(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);  
        
     // 加密由base64编码的签名  
        return Base64.encodeBase64String(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 = Base64.decodeBase64(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(Base64.decodeBase64(sign));  
    }  
  
    /** 
     * 解密<br> 
     * 用私钥解密 
     *  
     * @param data 
     * @param key 
     * @return 
     * @throws Exception 
     */  
    public static byte[] decryptByPrivateKey(byte[] data, String key)  
            throws Exception {  
        
        // 对密钥解密  
        byte[] keyBytes = Base64.decodeBase64(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 = Base64.decodeBase64(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 {  
        // base64 解密公钥
        byte[] keyBytes = Base64.decodeBase64(key);
        X509EncodedKeySpec  x509Key = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509Key);
        
         // 对数据加密
        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 = Base64.decodeBase64(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);  
    }  
       
    public static void main(String[] args) {
        // A向B发送数据
        try {

            byte[] pub_A = DesSecretUtil.readData("D://rsa-pub_A.pem");

            byte[] pri_A = DesSecretUtil.readData("D://rsa-pri_A.pem");

            byte[] pub_B = DesSecretUtil.readData("D://rsa-pub_B.pem");

            byte[] pri_B = DesSecretUtil.readData("D://rsa-pri_B.pem");
            
            String str = "开始测试";
            
            byte[] data = str.getBytes("UTF-8");
            
            //拿B的公钥加密
            byte[] encrptData = encryptByPublicKey(data, new String(pub_B));
            
            System.out.println("加密后Base64数据:"+Base64.encodeBase64String(encrptData));
            
            
            //拿B的私钥解密
            byte[] decrptData = decryptByPrivateKey(encrptData,new String(pri_B));
            
            System.out.println("解密后明文:"+new String(decrptData,"UTF-8"));

            
            
            // A的私钥数字签名
            String sign = sign(encrptData,new String(pri_A));
            
            // 加密由base64编码的签名  
            System.out.println("加密由base64编码的签名 :"+sign);            
            
            
            // A的公钥数字签名验证是否信息被篡改
            
            boolean flag = verify(decrptData,new String(pub_A),sign);
                    
            System.out.println("数字签名验证 :"+flag);
                        
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }

 

 
 
 
 
posted on 2016-02-04 18:22  惋红曲  阅读(498)  评论(0编辑  收藏  举报