用勿龍潛 / code / RSA加密解密及数字签名Java实现

分享

   

RSA加密解密及数字签名Java实现

2014-03-24  用勿龍潛
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

    RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密算法

    RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。

    关于RSA算法的原理,这里就不再详加介绍,网上各种资源一大堆。下面就开始介绍RSA加密解密JAVA类的具体实现。

01import java.security.MessageDigest;
02 
03import sun.misc.BASE64Decoder;
04import sun.misc.BASE64Encoder;
05 
06public class Coder {
07     
08    public static final String KEY_SHA="SHA";
09    public static final String KEY_MD5="MD5";
10     
11    /**
12     * BASE64解密
13     * @param key
14     * @return
15     * @throws Exception
16     */
17    public static byte[] decryptBASE64(String key) throws Exception{
18        return (new BASE64Decoder()).decodeBuffer(key);
19    }
20     
21    /**
22     * BASE64加密
23     * @param key
24     * @return
25     * @throws Exception
26     */
27    public static String encryptBASE64(byte[] key)throws Exception{
28        return (new BASE64Encoder()).encodeBuffer(key);
29    }
30     
31    /**
32     * MD5加密
33     * @param data
34     * @return
35     * @throws Exception
36     */
37    public static byte[] encryptMD5(byte[] data)throws Exception{
38        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
39        md5.update(data);
40        return md5.digest();
41    }
42     
43    /**
44     * SHA加密
45     * @param data
46     * @return
47     * @throws Exception
48     */
49    public static byte[] encryptSHA(byte[] data)throws Exception{
50        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
51        sha.update(data);
52        return sha.digest();
53    }
54}

     先提供Coder编码类,该类封装了基本的Base64、md5和SHA加密解密算法。Java对这些算法的实现提供了很好的API封装,开发人员只需调用这些API就可很简单方便的实现数据的加密与解密。

    下面提供RSA加密解密类,该类为Coder类子类,因为其中对RSA公私密钥的保存进行了一层Base64加密处理。

    RSA加密解密类静态常量

1   public static final String KEY_ALGORTHM="RSA";//
2public static final String SIGNATURE_ALGORITHM="MD5withRSA";
3 
4public static final String PUBLIC_KEY = "RSAPublicKey";//公钥
5public static final String PRIVATE_KEY = "RSAPrivateKey";//私钥


    RSA加密解密的实现,需要有一对公私密钥,公私密钥的初始化如下:

01/**
02     * 初始化密钥
03     * @return
04     * @throws Exception
05     */
06    public static Map<String,Object> initKey()throws Exception{
07        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
08        keyPairGenerator.initialize(1024);
09        KeyPair keyPair = keyPairGenerator.generateKeyPair();
10         
11        //公钥
12        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
13        //私钥
14        RSAPrivateKey privateKey =  (RSAPrivateKey) keyPair.getPrivate();
15         
16        Map<String,Object> keyMap = new HashMap<String, Object>(2);
17        keyMap.put(PUBLIC_KEY, publicKey);
18        keyMap.put(PRIVATE_KEY, privateKey);
19         
20        return keyMap;
21    }

      从代码中可以看出密钥的初始化长度为1024位,密钥的长度越长,安全性就越好,但是加密解密所用的时间就会越多。而一次能加密的密文长度也与密钥的长度成正比。一次能加密的密文长度为:密钥的长度/8-11。所以1024bit长度的密钥一次可以加密的密文为1024/8-11=117bit。所以非对称加密一般都用于加密对称加密算法的密钥,而不是直接加密内容。对于小文件可以使用RSA加密,但加密过程仍可能会使用分段加密。

    从map中获取公钥、私钥

01/**
02     * 取得公钥,并转化为String类型
03     * @param keyMap
04     * @return
05     * @throws Exception
06     */
07    public static String getPublicKey(Map<String, Object> keyMap)throws Exception{
08        Key key = (Key) keyMap.get(PUBLIC_KEY); 
09        return encryptBASE64(key.getEncoded());    
10    }
11 
12    /**
13     * 取得私钥,并转化为String类型
14     * @param keyMap
15     * @return
16     * @throws Exception
17     */
18    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{
19        Key key = (Key) keyMap.get(PRIVATE_KEY); 
20        return encryptBASE64(key.getEncoded());    
21    }

    对于RSA产生的公钥、私钥,我们可以有两种方式可以对信息进行加密解密。私钥加密-公钥解密 和 公钥加密-私钥解密。

    私钥加密

01/**
02     * 用私钥加密
03     * @param data  加密数据
04     * @param key   密钥
05     * @return
06     * @throws Exception
07     */
08    public static byte[] encryptByPrivateKey(byte[] data,String key)throws Exception{
09        //解密密钥
10        byte[] keyBytes = decryptBASE64(key);
11        //取私钥
12        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
13        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
14        Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
15         
16        //对数据加密
17        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
18        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
19         
20        return cipher.doFinal(data);
21    }

    私钥解密

01/**
02     * 用私钥解密<span style="color:#000000;"></span> * @param data  加密数据
03     * @param key   密钥
04     * @return
05     * @throws Exception
06     */
07    public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{
08        //对私钥解密
09        byte[] keyBytes = decryptBASE64(key);
10         
11        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
12        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
13        Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
14        //对数据解密
15        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
16        cipher.init(Cipher.DECRYPT_MODE, privateKey);
17         
18        return cipher.doFinal(data);
19    }
    公钥加密
01/**
02     * 用公钥加密
03     * @param data  加密数据
04     * @param key   密钥
05     * @return
06     * @throws Exception
07     */
08    public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{
09        //对公钥解密
10        byte[] keyBytes = decryptBASE64(key);
11        //取公钥
12        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
13        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
14        Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
15         
16        //对数据解密
17        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
18        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
19         
20        return cipher.doFinal(data);
21    }
    私钥加密
01/**
02     * 用公钥解密
03     * @param data  加密数据
04     * @param key   密钥
05     * @return
06     * @throws Exception
07     */
08    public static byte[] decryptByPublicKey(byte[] data,String key)throws Exception{
09        //对私钥解密
10        byte[] keyBytes = decryptBASE64(key);