2019独角兽企业重金招聘Python工程师标准>>>

基本概念:

数字签名,顾名思义,就类似于一种写在纸上的普通的物理签名.

简单说就是将文件内容进行hash散列(消息摘要),信息发送者对散列后的字符串使用私钥加密,得到的最终字符串就是签名。然后将得到的签名字符串添加到文件信息的后面一同发送出去。接收者获取到文件信息和签名后,使用公钥对签名进行解密,就得到文件内容和加密后的hash散列。此时,他可以对获取到的文件内容做hash散列,与签名中的hash散列进行匹对,从而鉴别出最终获取信息的真伪.

整个过程可以用如下图解理解.

算法种类:

常见的几种KeyPairGenerator算法

KeyPairGenerator Algorithms

(除了指出,这些类创建Key.getAlgorithm()返回标准算法名称的密钥.)

生成KeyPairGenerator实例时可以指定本节中的算法名称.

Algorithm Name Description
DiffieHellman 为Diffie-Hellman密钥协商算法生成密钥对。
注意:key.getAlgorithm()将返回“DH”而不是“DiffieHellman”。
DSA Generates keypairs for the Digital Signature Algorithm.
RSA Generates keypairs for the RSA algorithm (Signature/Cipher).
EC Generates keypairs for the Elliptic Curve algorithm.

常见的签名算法

Signature Algorithms

生成Signature实例时可以指定本节中的算法名称。

Algorithm Name Description
NONEwithRSA RSA签名算法在执行RSA操作之前不使用摘要算法(例如MD5 /SHA1)。 
MD2withRSA
MD5withRSA
使用MD2 / MD5摘要算法和RSA来创建和验证
SHA1withRSA
SHA224withRSA
SHA256withRSA
SHA384withRSA
SHA512withRSA
使用  SHA- *  的签名算法和OSI Interoperability Workshop中定义的RSA加密算法
NONEwithDSA

FIPS PUB 186-2中定义的数字签名算法。 数据长度必须是20个字节。 这个算法也被称为rawDSA。

SHA1withDSA
SHA224withDSA
SHA256withDSA

DSA签名算法使用SHA-1,SHA-224或SHA-256摘要算法来创建和验证

NONEwithECDSA
SHA1withECDSA
SHA224withECDSA
SHA256withECDSA
SHA384withECDSA
SHA512withECDSA
(ECDSA)

ECDSA签名算法。
注意:“ECDSA”是“SHA1withECDSA”算法的模糊名称,不应使用。 应该使用正式名称“SHA1withECDSA”。

<digest>with<encryption>

使用这个名称为具有特定消息摘要(如MD2或MD5)和算法(如RSA或DSA)的签名算法创建一个名称,就像本节中明确定义的标准名称(MD2withRSA等)一样 上)

code实例:

DataSecurity:

package com.fitc.soldier.service.common;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;import org.apache.commons.codec.binary.Hex;public class DataSecurity {private static String  testContent="这是一个测试文本!!!";public static void main(String[] args) {//       localKeyPairMethod(testContent);
//      localPrivatKeyMethod(testContent);generatorKey(testContent);}/*** 加载本地密钥对*/public static void localKeyPairMethod(String Content){try {File file = new File("ca.key");FileOutputStream fileOutputStream = new FileOutputStream(file);//加载本地KeyPair 密钥对KeyPair keyPair = KeyPairUtil.generatorkeyPair();KeyPairUtil.storeKeyPair(keyPair, fileOutputStream);KeyPair localFileKeyPair = KeyPairUtil.localFileKeyPair(new FileInputStream(file));PublicKey publicKey = localFileKeyPair.getPublic();PrivateKey privateKey = localFileKeyPair.getPrivate();DataSignaturer dataSignaturer=new DataSignaturer(privateKey, publicKey);byte[] sign = dataSignaturer.sign(Content.getBytes());System.out.println("签名:\t"+Hex.encodeHexString(sign));System.out.println("验证签名结果\t"+dataSignaturer.verifySign(Content.getBytes(), sign));} catch (FileNotFoundException | NoSuchAlgorithmException e) {e.printStackTrace();}}/*** 加载本地私钥/公钥  对数据实现签名和验证*/public static void localPrivatKeyMethod(String Content){try {File private_key_File = new File("private_key.key");File public_key_File = new File("public_key.key");FileOutputStream private_keytStream = new FileOutputStream(private_key_File);FileOutputStream public_keyStream = new FileOutputStream(public_key_File);//生成本地密钥 分别存储本地 KeyPair keyPair = KeyPairUtil.generatorkeyPair();KeyPairUtil.storeKeyPair(keyPair, private_keytStream, public_keyStream);//加载本地密钥文件PrivateKey loadFilePrivateKey = KeyPairUtil.loadFilePrivateKey(new FileInputStream(private_key_File));PublicKey loadFilePublicKey = KeyPairUtil.loadFilePublicKey(new FileInputStream(public_key_File));DataSignaturer dataSignaturer=new DataSignaturer(loadFilePrivateKey, loadFilePublicKey);byte[] sign = dataSignaturer.sign(Content.getBytes());System.out.println("签名:\t"+Hex.encodeHexString(sign));System.out.println("签名:\t"+StringHelper.encoderBase64(sign));System.out.println("验证签名结果\t"+dataSignaturer.verifySign(Content.getBytes(), sign));} catch (FileNotFoundException | NoSuchAlgorithmException e) {e.printStackTrace();}}/*** 使用密钥对 构建公私钥  对数据进行签名和验证*/public static void generatorKey(String Content){try {//生成密钥KeyPair keyPair = KeyPairUtil.generatorkeyPair();PrivateKey privateKey = keyPair.getPrivate();PublicKey publicKey = keyPair.getPublic();KeyFactory keyFactory=KeyFactory.getInstance(KeyPairUtil.KEY_ALGORITHM);
//               将生成的密钥  按照PKCS#8标准作为密钥规范管理的编码格式 转换成 密钥
//               在 Java 语言中,此类表示基于在 PKCS 8 标准中定义的 ASN.1 类型的编码密钥PKCS8EncodedKeySpec pkcs8encodedkeyspec=new PKCS8EncodedKeySpec(privateKey.getEncoded());PrivateKey generatePrivate = keyFactory.generatePrivate(pkcs8encodedkeyspec);//使用密钥签名  SHA1withRSA 签名算法Signature signature=Signature.getInstance("SHA1withRSA");signature.initSign(generatePrivate);signature.update(Content.getBytes());byte[] sign = signature.sign();System.out.println("原文内容:\t"+Content);System.out.println("签名结果:\t"+Hex.encodeHexString(sign));//创建公钥 ,使用公钥验证签名 X509EncodedKeySpec  ASN.1 类型的编码密钥X509EncodedKeySpec  x509encodedkeyspec=new X509EncodedKeySpec(publicKey.getEncoded());PublicKey generatePublic  = keyFactory.generatePublic(x509encodedkeyspec);signature.initVerify(generatePublic);signature.update(Content.getBytes());System.out.println("原文内容:\t"+Content);System.out.println("验证签名是否通过:\t"+signature.verify(sign));} catch (NoSuchAlgorithmException | InvalidKeySpecException | SignatureException | InvalidKeyException e) {e.printStackTrace();}}}

KeyPairUtil(密钥对的生成或者 加载本地密钥文件):

package com.fitc.soldier.service.common;import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;/*** <pre>*公钥,私钥生成工具类</br>*可以又 KeyPairGenerator 秘钥对生成器生成然后保存到本地</br>*或者直接读取本地的密钥文件*</pre>*/public class KeyPairUtil {// 可以用DSA,也可以用RSA    public static final String KEY_ALGORITHM="RSA"; /*** 从输入流中获取KeyPair 秘钥对 对象* @param keyPairStream 输入流* @return*/public static KeyPair localFileKeyPair(InputStream keyPairStream){if (keyPairStream==null) {System.out.println("指定的输入流=null!因此无法读取KeyPair!");return null;}ObjectInputStream objectInputStream=null;try {objectInputStream=new ObjectInputStream(keyPairStream);KeyPair keyPair =(KeyPair)objectInputStream.readObject();objectInputStream.close();return keyPair;} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}finally {if (objectInputStream!=null) {try {objectInputStream.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}return null;}/*** 从本地文件加载公钥* @param publicKeyInputStream  输入流* @return*/public static PublicKey loadFilePublicKey(InputStream  publicKeyInputStream){ObjectInputStream objectInputStream=null;try {objectInputStream=new ObjectInputStream(publicKeyInputStream);PublicKey  publickey = (PublicKey)objectInputStream.readObject();objectInputStream.close();return publickey;} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}finally {if (objectInputStream!=null) {try {objectInputStream.close();} catch (IOException e) {e.printStackTrace();}}}return null;}/*** 从本地文件加载私钥* @param PrivateKeyInputStream 输入流* @return*/public static PrivateKey  loadFilePrivateKey(InputStream  PrivateKeyInputStream){ObjectInputStream objectInputStream=null;try {objectInputStream=new ObjectInputStream(PrivateKeyInputStream);PrivateKey  privatekey = (PrivateKey)objectInputStream.readObject();objectInputStream.close();return privatekey;} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}finally {if (objectInputStream!=null) {try {objectInputStream.close();} catch (IOException e) {e.printStackTrace();}}}return null;}/*** 将整个KeyPair密钥对 对象存在本地文件* * @param keyPair 公钥私钥对对象* @param out 输出流* @return*/public  static boolean storeKeyPair(KeyPair keyPair,OutputStream out){if ((keyPair == null) || (out == null)) {System.out.println("keyPair  or OutputStream is null ");return false;}ObjectOutputStream objectOutputStream=null;try {objectOutputStream = new ObjectOutputStream(out);objectOutputStream.writeObject(keyPair);objectOutputStream.close();return true;} catch (IOException e) {e.printStackTrace();} finally {if (objectOutputStream != null) {try {objectOutputStream.close();} catch (IOException e) {e.printStackTrace();}}}return false;}/***将公钥,私钥分开存储在IO流中* @param keyPair 公钥私钥对对象* @param out 输出流* @return*/public  static boolean storeKeyPair(KeyPair keyPair,OutputStream privateKeyOut,OutputStream publicKeyOut){PrivateKey privateKey = keyPair.getPrivate();PublicKey publicKey=keyPair.getPublic();boolean resut=false;if (keyPair==null||privateKeyOut==null||publicKeyOut==null) {System.out.println("指定的IO流或者密钥对 对象为null");return resut;}ObjectOutputStream privateKeyStream = null;ObjectOutputStream publicKeyStream = null;try {privateKeyStream = new ObjectOutputStream(privateKeyOut);privateKeyStream.writeObject(privateKey);publicKeyStream = new ObjectOutputStream(publicKeyOut);publicKeyStream.writeObject(publicKey);resut = true;privateKeyStream.close();publicKeyStream.close();} catch (IOException e) {e.printStackTrace();}finally {if (privateKeyStream!=null&&publicKeyStream!=null) {try {privateKeyStream.close();publicKeyStream.close();} catch (IOException e) {e.printStackTrace();}}}return resut;}/*** 生成KeyPair公钥私钥对* * @return*/public static KeyPair generatorkeyPair(){try {KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM);keyPairGenerator.initialize(1024);return keyPairGenerator.generateKeyPair();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return null;}
}

DataSignaturer(实现签名和验证):

package com.fitc.soldier.service.common;import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;/**<pre>* 实现数字签名的类* X509EncodedKeySpec和PKCS8EncodedKeySpec两个类在加密解密环节中经常会用到。* 密钥很可能会以二进制方式存储于文件中,由程序来读取。这时候,就需要通过这两个类将文件中的字节数组* 读出转换为密钥对象。*  </pre>*/
public class DataSignaturer {/*** 私钥*/private PrivateKey privateKey;/*** 公钥*/private PublicKey publicKey;/*** key 工厂*/private KeyFactory keyFactory;public DataSignaturer(PrivateKey privateKey, PublicKey publicKey) throws NoSuchAlgorithmException {super();this.privateKey = privateKey;this.publicKey = publicKey;this.keyFactory=KeyFactory.getInstance(privateKey.getAlgorithm());}/*** 进行数字签名* @param data* @return*/public   byte[] sign(byte[] resoure){if (privateKey==null||publicKey==null) {System.out.println("privateKey or publicKey  is null ");return null;}try {
//          初始化签名算法//           String signatuureAlgorithm="";
//          if (algorithm.equals("RSA")) {
//              signatuureAlgorithm="MD5withRSA";
//          signatuureAlgorithm="SHA1withRSA";
//          }else if (algorithm.equals("DSA")) {
//              signatuureAlgorithm="SHA1withDSA";
//          }else {
//              signatuureAlgorithm="SHA1withECDSA";
//          }//         或者为了方便统一使用SHA1with**的签名算法PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded()); PrivateKey privatekey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Signature signature=Signature.getInstance("SHA1with"+privateKey.getAlgorithm());signature.initSign(privatekey);signature.update(resoure);return signature.sign();} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) {e.printStackTrace();}return null;}/*** 验证数字签名* @param data* @param signature* @return*/public boolean verifySign(byte[] resoure, byte[] signature) {if (privateKey == null || publicKey == null) {System.out.println("privateKey or publicKey  is null ");return false;}try {X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec (publicKey.getEncoded());PublicKey publickey = keyFactory.generatePublic(x509EncodedKeySpec);Signature verifySign = Signature.getInstance("SHA1with"+publicKey.getAlgorithm());verifySign.initVerify(publickey);verifySign.update(resoure);return verifySign.verify(signature);} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) {e.printStackTrace();}return false;}
}

StringHelper(Base64编码工具类):

package com.fitc.soldier.service.common;import java.io.IOException;import org.apache.commons.lang.StringUtils;import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;/*** *Base64的编解码*将密钥编码成Base64 以便传输和查看*/
public class StringHelper {/** * BASE64Encoder 加密 * @param data 要加密的数据 * @return 加密后的字符串 */  public static String encoderBase64(byte[] data){if (data==null||data.length==0) {return "";}BASE64Encoder base64Encoder = new BASE64Encoder();return base64Encoder.encode(data);}/** * BASE64Decoder 解密 * @param data 要解密的字符串 * @return 解密后的byte[] * @throws Exception  */  public static byte[] decoderBase64(String encodeString) throws IOException{if (StringUtils.isEmpty(encodeString)) {return null;}BASE64Decoder base64Encoder = new BASE64Decoder();return base64Encoder.decodeBuffer(encodeString);}}

console 输出:

总结.

在使用签名算法对数据进行数据签名和验证时,主要步骤

1.创建Signature对象

Signature verifySign = Signature.getInstance(String algorithm);//algorith为前面表格中的值

2.初始化:

Signature .initVerify(PublicKey publicKey)/Signature .initSign(PrivateKey privateKey)

3.填充数据:

Signature.update(byte[] data);

签名和验证

4.Signature.sign() 和 verify(byte[] signature)方法.

---------------------------------------------------分割线-----------------------------------------------

参考:https://www.cnblogs.com/huangzijian/p/6347293.html

转载于:https://my.oschina.net/u/3406827/blog/1600595

数字签名的java实现(RSA,DSA)相关推荐

  1. java RSA/DSA/ECDSA实现数字签名

    java RSA/DSA/ECDSA实现数字签名 标签: java RSADSAECDSA实现数字RSADSAECDSA实现数字签名 2015-12-13 14:51 1656人阅读 评论(0) 收藏 ...

  2. java使用RSA加密方式,实现数字签名

    全栈工程师开发手册 (作者:栾鹏) java教程全解 java使用RSA加密方式,实现数字签名.数字签名,使用私钥获取签名,使用公钥校验签名 测试代码 public static void main( ...

  3. JAVA加密算法(DSA)

    DSA  DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard) ...

  4. dsa java_将Java转换为python DSA签名

    有人知道我将如何将java代码转换成python吗?在/** * signs the data for the account account */ private byte[] sign(Strin ...

  5. 消息摘要和数字签名(Java简单实现)

    摘要: 本文主要对数字签名和消息摘要进行简要介绍,并通过java实现基本流程. 概念介绍: 消息摘要 一个消息摘要是一个数据块的数字指纹.即对一个任意长度的一个数据块进行计算,产生一个唯一指印(对于 ...

  6. Java前端Rsa公钥加密,后端Rsa私钥解密(支持字符和中文)

    Base64工具类,可以让rsa编码的乱码变成一串字符序列 package com.utils;import java.io.ByteArrayInputStream; import java.io. ...

  7. java中RSA数字证书生成,jks文件生成以及读取。

    一.Java代码生成cer证书文件: public class GetCertFile { //证书颁发者     static String CertificateIssuer = "C= ...

  8. java的rsa作用_java 中RSA的方式实现非对称加密的实例

    java 中rsa的方式实现非对称加密的实例 rsa通俗理解: 你只要去想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密:同理,既然是签名,那肯 ...

  9. javascript rsa java,用javascript与java执行 RSA加密与解密

    用javascript与java执行 RSA加密与解密 2009-12-12 14:58:30   出处:https://www.yqdown.com 这几天一直做安全登录,网上查了好多资料,不尽如意 ...

最新文章

  1. 大触教你如何调节python内置函数
  2. vim-addon-manager install youcompleteme
  3. vtune下载 windows_intel vtune 介绍、安装和使用
  4. lua调用.so测试
  5. SQL笛卡尔积结合前后行数据的统计案例
  6. CSRF 1 (转)
  7. 使用router-view时组件之间的通信
  8. 评审专家:基金本子“瘦”点好
  9. CVPR 2020 | 3D目标检测泛化问题研究
  10. Android笔记 fragment入门 动态加载fragment demo+ 判断横竖屏
  11. nodejs在自然语言处理中的一些小应用
  12. 读嵌入式linux驱动程序设计从入门到精通1
  13. google 搜索关键字技巧 google darking
  14. [从源码学设计]蚂蚁金服SOFARegistry之服务上线
  15. Mysql Buffer Pool
  16. RSPO棕榈油供应链认证体系
  17. iPhone软件开发前需认真考虑问题
  18. Glib之GObject简介(翻译)
  19. 进程互斥锁,队列,IPC进程间通信,生产者与消费者,线程,线程对象的属性,先行互斥锁...
  20. Cartov for Mac 1.0.2 无尽旅图

热门文章

  1. mysql noinstall_免安装版MySql安装与配置
  2. 服务器端Session和客户端Session
  3. java线程间通信:一个小Demo完全搞懂
  4. 第一冲刺阶段工作总结02
  5. Sublime Text3 高亮显示Jade语法 (Windows 环境)
  6. Segment,Path,Ring和Polyline对象
  7. 一些必不可少的Sublime Text 2插件
  8. [导入]c#中的关于string的转换的问题
  9. x86的32位汇编快速入门
  10. c#双缓冲绘图(不闪烁的几种方法)