RSA加解密

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

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

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

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

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

 

import java.security.MessageDigest; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class Coder { public static final String KEY_SHA="SHA"; public static final String KEY_MD5="MD5"; /**  * BASE64解密  * @param key  * @return  * @throws Exception  */ public static byte[] decryptBASE64(String key) throws Exception{ return (new BASE64Decoder()).decodeBuffer(key); } /**  * BASE64加密  * @param key  * @return  * @throws Exception  */ public static String encryptBASE64(byte[] key)throws Exception{ return (new BASE64Encoder()).encodeBuffer(key); } /**  * MD5加密  * @param data  * @return  * @throws Exception  */ public static byte[] encryptMD5(byte[] data)throws Exception{ MessageDigest md5 = MessageDigest.getInstance(KEY_MD5); md5.update(data); return md5.digest(); } /**  * SHA加密  * @param data  * @return  * @throws Exception  */ public static byte[] encryptSHA(byte[] data)throws Exception{ MessageDigest sha = MessageDigest.getInstance(KEY_SHA); sha.update(data); return sha.digest(); } }

 

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

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

    RSA加密解密类静态常量编码

 

       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";//私钥

 

 

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

 

/**  * 初始化密钥  * @return  * @throws Exception  */ 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; }

 

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

    从map中获取公钥、私钥code

 

/**  * 取得公钥,并转化为String类型  * @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());      } /**  * 取得私钥,并转化为String类型  * @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());      }

 

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

    私钥加密

 

/**
	 * 用私钥加密
	 * @param data 加密数据  * @param key 密钥  * @return  * @throws Exception  */ public static byte[] encryptByPrivateKey(byte[] data,String key)throws Exception{ //解密密钥 byte[] keyBytes = decryptBASE64(key); //取私钥 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); //对数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODEprivateKey); return cipher.doFinal(data); }

 

    私钥解密

 

/**
	 * 用私钥解密 * @param data  加密数据  * @param key 密钥  * @return  * @throws Exception  */ public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{ //对私钥解密 byte[] keyBytes = decryptBASE64(key); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); //对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODEprivateKey); return cipher.doFinal(data); }

    公钥加密

/**
	 * 用公钥加密
	 * @param data 加密数据  * @param key 密钥  * @return  * @throws Exception  */ public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{ //对公钥解密 byte[] keyBytes = decryptBASE64(key); //取公钥 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); //对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODEpublicKey); return cipher.doFinal(data); }

    私钥加密

/**
	 * 用公钥解密
	 * @param data 加密数据  * @param key 密钥  * @return  * @throws Exception  */ public static byte[] decryptByPublicKey(byte[] data,String key)throws Exception{ //对私钥解密 byte[] keyBytes = decryptBASE64(key); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); //对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODEpublicKey); return cipher.doFinal(data); }

 

    关于数字签名,先了解下何为数字签名。数字签名,就是只有信息的发送者才能产生的别人没法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证实。数字签名是非对称密钥加密技术与数字摘要技术的应用。简单地说,所谓数字签名就是附加在数据单元上的一些数据,或是对数据单元所做的密码变换。这种数据或变换容许数据单元的接收者用以确认数据单元的来源和数据单元的完整性并保护数据,防止被人(例如接收者)进行伪造。

    数字签名的主要功能以下:
 

 

    保证信息传输的完整性、发送者的身份认证、防止交易中的抵赖发生。

    数字签名技术是将摘要信息用发送者的私钥加密,与原文一块儿传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息,而后用对收到的原文产生一个摘要信息,与解密的摘要信息对比。若是相同,则说明收到的信息是完整的,在传输过程当中没有被修改,不然说明信息被修改过,所以数字签名可以验证信息的完整性。

    数字签名是个加密的过程,数字签名验证是个解密的过程。

     数字签名算法依靠公钥加密技术来实现的。在公钥加密技术里,每个使用者有一对密钥:一把公钥和一把私钥。公钥能够自由发布,但私钥则秘密保存;还有一个要求就是要让经过公钥推算出私钥的作法不可能实现。

    普通的数字签名算法包括三种算法:

    1.密码生成算法;

    2.标记算法;

   3.验证算法。

    经过RSA加密解密算法,咱们能够实现数字签名的功能。咱们能够用私钥对信息生成数字签名,再用公钥来校验数字签名,固然也能够反过来公钥签名,私钥校验。

    私钥签名
 

 

/**  * 用私钥对信息生成数字签名  * @param data //加密数据  * @param privateKey //私钥  * @return  * @throws Exception  */ public static String sign(byte[] data,String privateKey)throws Exception{ //解密私钥 byte[] keyBytes = decryptBASE64(privateKey); //构造PKCS8EncodedKeySpec对象 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); //指定加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); //取私钥匙对象 PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec); //用私钥对信息生成数字签名 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(privateKey2); signature.update(data); return encryptBASE64(signature.sign()); }

    公钥校验 

 

 

/**  * 校验数字签名  * @param data 加密数据  * @param publicKey 公钥  * @param sign 数字签名  * @return  * @throws Exception  */ public static boolean verify(byte[] data,String publicKey,String sign)throws Exception{ //解密公钥 byte[] keyBytes = decryptBASE64(publicKey); //构造X509EncodedKeySpec对象 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); //指定加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); //取公钥匙对象 PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicKey2); signature.update(data); //验证签名是否正常 return signature.verify(decryptBASE64(sign)); }
相关文章
相关标签/搜索