加密解密算法

1.加密算法的分类

对称加密
加密的密钥和解密的密钥是相同的, 也叫私钥算法. 这种算法的密钥是不能公开的, 否则加密就形同虚设. 常见的算法有 DES加密, AES 加密等

非对称加密
加密的密钥和解密的密钥是不同的. 也叫公钥算法. 公钥用来加密, 私钥用来解密.

2.常用的加密方法

使用对称加密的好处是加密解密速度较快,效率高,但双方都使用相同的密钥, 安全性不高. 非对称加密,算法较复杂, 加密解密相对对称加密会比较慢. 结合两种算法的特性, 推荐的做法是:

1. 接收方生成一对公钥和密钥
2. 接收方将公钥发送给发送方
2. 发送方将使用公钥加密的会话密钥和使用会话密钥加密后的报文发送给接收方
3. 接收方首先使用私钥将加密后的会话密钥进行解密,然后再使用会话密钥将报文解密

3. Java实现示例

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
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;

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

public class Utils {
    public static final String KEY_ALGORTHM = "RSA";//
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    public static final String PUBLIC_KEY = "RSAPublicKey";// 公钥
    public static final String PRIVATE_KEY = "RSAPrivateKey";// 私钥

    // 生成公钥和密钥
    public static Map<String, Object> initKey() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator
                .getInstance(KEY_ALGORTHM);
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.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;
    }

    // 获取公钥
    public static String getPublicKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return encryptBASE64(key.getEncoded());
    }

    // 获取私钥
    public static String getPrivateKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return encryptBASE64(key.getEncoded());
    }

    // BASE64, 方便网络传输
    public static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }



    public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{
        //对公钥解密
        byte[] keyBytes = Utils.decryptBASE64(key);
        //取公钥
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(Utils.KEY_ALGORTHM);
        Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        return cipher.doFinal(data);
    }

    public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{
        //对私钥解密
        byte[] keyBytes = Utils.decryptBASE64(key);

        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(Utils.KEY_ALGORTHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        return cipher.doFinal(data);
    }


}

Test.java

import java.util.Map;

public class Test {
    public static void main(String[] args) {
        String text = "Hello RSA";
        try {
            // 初始化公钥和私钥
            Map<String,Object> keyMap = Utils.initKey();
            //获取公钥和私钥
            String publicKey = Utils.getPublicKey(keyMap);
            String privateKey = Utils.getPrivateKey(keyMap);
            System.out.println("privateKey = "+privateKey+";publicKey = " + publicKey);

            byte[] encryptBytes = Utils.encryptByPublicKey(text.getBytes(), publicKey);
            byte[] decryptBytes = Utils.decryptByPrivateKey(encryptBytes, privateKey);

            String result = new String(decryptBytes);
            System.out.println("Text = " + result);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

运行结果:

privateKey = MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKbNb4ovjR2xuhmAnaJnImuXL7fY
huxIOqsVHtVtn8Gki/J2Vox3PFfoU5bpxdH4+dKmZm5TuNPXfeLnlCjWe9S/CuSHJ9uXbXrimtRp
WlwwsCEPNW3//PZq7E5ADeO+HjEdKTUWd7mMMzXQfY37BhS2MaBC3TnZZ0vFO/dGvjq1AgMBAAEC
gYEApC5TmoWBdffowI9bGW5Ab/xJCMGE1G+n55uLVPJpLBYFdetK90mpyLEyDboeb7WMWO5WpkOc
Ck/yZfQhXiz3hnJYvOqxMGOXfJyb3T+gdPap3V+PvhTrDL1ZqP5mt07d6RA7hVSJ3IuipF2gq1jH
V+K/w2+iEMR1rJEZElL8nWECQQDVwiRQiCS11okOuDUBvG2r9n9jkBBAvR0V+FlLdc5+xRqGjd61
p5tzOwAN7QWYW6pIJ6MD2XCm/PavVi+2fqLdAkEAx8PVsISQrDqVYC0MtXowQdf4lZKGXuBXyNVX
jdpnHNMaGJAdtfo/WygQGvC6EOkbwrvFqjUmNsZqL/HWnK2duQJAYHTjuCdHEXrGjArZeHgTsSZh
I4dNnjj4GALiIGf/jzrYFmGMXsJMJjo4cxBClxa+ByNDryf+aov5sPMeQqZwTQJAVdzV14ZTTMPt
eqZCZSp83YA/58JQIS2abcdNV7p9QYV3HQGs05AZdUv2CC5aO3SGqx/caTlpEHgeIjd3gGabeQJA
LX0uM2jLjPDrJTU4XfSCKOgdGvYpmA0CRz7WHv8WHnNCpf/XGm1I7rcC5JzVQF6s2RyqRE5c8PWS
WLTC3mZQng==
;publicKey = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmzW+KL40dsboZgJ2iZyJrly+32IbsSDqrFR7V
bZ/BpIvydlaMdzxX6FOW6cXR+PnSpmZuU7jT133i55Qo1nvUvwrkhyfbl2164prUaVpcMLAhDzVt
//z2auxOQA3jvh4xHSk1Fne5jDM10H2N+wYUtjGgQt052WdLxTv3Rr46tQIDAQAB

Text = Hello RSA

这里生成的私钥和公钥每次都是不同的, 所以不会有被获取的风险.

参考资料:

  1. 《理解公钥与私钥》
  2. 《公钥,私钥,SSL(讲的很生动)》
  3. 《Swift - 使用RSA算法进行数据加密,解密以及数字签名》
2015-12-22 23:151