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

RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密算法。
RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
关于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编码类,该类封装了基本的Base64、md5和SHA加密解密算法。Java对这些算法的实现提供了很好的API封装,开发人员只需调用这些API就可很简单方便的实现数据的加密与解密。
下面提供RSA加密解密类,该类为Coder类子类,因为其中对RSA公私密钥的保存进行了一层Base64加密处理。
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加密,但加密过程仍可能会使用分段加密。
从map中获取公钥、私钥

/**
 * 取得公钥,并转化为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_MODE, privateKey);

    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_MODE, privateKey);
    
    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_MODE, publicKey);

    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_MODE, publicKey);

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

}

对于RSA如何加密文件、图片等信息,加密的信息又如何保存,怎样保存解密后的信息,以及操作过程中遇到的错误将如何处理,将在后面的文章中介绍给大家。

分享一份spring cloud视频
关注公众号回复 springcloud 获取

原文地址:http://blog.51cto.com/13538361/2067057

时间: 2024-10-20 16:26:31

RSA加密解密及数字签名Java实现的相关文章

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

RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.当时他们三人都在麻省理工学院工作.RSA就是他们三人姓氏开头字母拼在一起组成的. RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密算法. RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密. 关于RSA算法

C#-java RSA加密解密

using Org.BouncyCastle.Math;using Org.BouncyCastle.Crypto.Parameters;using Org.BouncyCastle.Security;using Org.BouncyCastle.Asn1.X509;using Org.BouncyCastle.X509;using Org.BouncyCastle.Asn1.Pkcs;using Org.BouncyCastle.Pkcs;using System;using System.S

JAVA实现RSA加密解密 非对称算法

首先RSA是一个非对称的加密算法,所以在使用该算法加密解密之前,必须先行生成密钥对,包括公钥和私钥 JDK中提供了生成密钥对的类KeyPairGenerator,实例如下: public static Map<String, Object> genKeyPair() throws Exception { // 获取公钥私钥密钥对的生成器 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); // 初始化确定密

Java使用RSA加密解密签名及校验

由于项目要用到非对称加密解密签名校验什么的,于是参考<Java加密解密的艺术>写一个RSA进行加密解密签名及校验的Demo,代码很简单,特此分享! RSA加密解密类: package com.ihep; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; imp

C# Java间进行RSA加密解密交互

引用:http://blog.csdn.net/dslinmy/article/details/37362661 这里,讲一下RSA算法加解密在C#和Java之间交互的问题,这两天纠结了很久,也看了很多其他人写的文章,颇受裨益,但没能解决我的实际问题,终于,还是被我捣鼓出来了. 首先,介绍一下写这代码的目的:完成webService验证问题,服务器端采用C#开发,客户端采用Java开发.服务器端给客户端提供公钥,已进行数据加密,客户端加密后提数据提交给服务器,服务器用私钥对数据解密,进行验证.

C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法

因为C#的RSA加密解密只有公钥加密,私钥解密,没有私钥加密,公钥解密.在网上查了很久也没有很好的实现.BouncyCastle的文档少之又少.很多人可能会说,C#也是可以的,通过Biginteger开源类来实现,不过那个是有一个文章,不过他加密出来的是16进制结果的.根本不能和JAVA互通.连加密出来的都不和C#原生的加密出来的结果格式一样.所以还是没有好的解决方法. 接下来还是不断的找资料,找方法.找朋友找同事.个个都找.问题是有的,方法也是有的,所以总结各路大神之后写了这个类.实现了私钥加

RSA加密解密及RSA加签验签

RSA安全性应用场景说明 在刚接触RSA的时候,会混淆RSA加密解密和RSA加签验签的概念.简单来说加密解密是公钥加密私钥解密,持有公钥(多人持有)可以对数据加密,但是只有持有私钥(一人持有)才可以解密并查看数据:加签验签是私钥加签公钥验签,持有私钥(一人持有)可以加签,持有公钥(多人持有)可以验签. 在金融行业在设计到数据交互传输的时候,需要考虑数据的安全性问题.下文通过介绍RSA的加密和加签两个特性,说明RSA加密技术在保障数据传输过程中的安全性以及实现数据的防篡改和防否机制的应用场景及代码

RSA加密解密(转)

RSA加密解密 对于RSA产生的公钥.私钥,我们可以有两种方式可以对信息进行加密解密.私钥加密-公钥解密 和 公钥加密-私钥解密RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.当时他们三人都在麻省理工学院工作.RSA就是他们三人姓氏开头字母拼在一起组成的. RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密算法.

python RSA加密解密及模拟登录cnblog

1.公开密钥加密 又称非对称加密,需要一对密钥,一个是私人密钥,另一个则是公开密钥.公钥加密的只能私钥解密,用于加密客户上传数据.私钥加密的数据,公钥可以解密,主要用于数字签名.详细介绍可参见维基百科. 2.RSA加密算法 RSA加密属于非对称加密.RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥.维基百科中对RSA算法的安全性进行说明:RSA加密算法 "对极大整数做因式分解的难度决定了RSA算法的可靠性.换言