密码学研究-数字签名
引入:
提到签名,大家都不陌生,大家知道,重大的文件一般都要领导签名,来确保这个文件的真实有效。而一些比较重要的合同,比如买房的购房合同,都要盖“骑缝章”,这个骑缝章,就是盖在2页纸中间的印章,它也代表了签名,它用来保证你合同的完整性。所以说,签名在日常生活中非常重要,它主要用来保证了信息的完整性。同样,计算机世界也对这个签名过程进行了模拟,数字签名的概念由此而生。
数字签名的过程:
一般数字签名的过程分为2个,一个是签名过程,一个是验证过程。
数字签名的基本过程如下:
(1)发送方用指定的散列函数作用于原始报文,计算出原始报文的原始摘要。
(2)发送方选用非对称的密钥中的私钥对原始摘要进行加密,得到加密后的原始摘要
(3)发送方构造一个报文(SignedObject对象),将原始报文添加在其中
(4)发送方将第(2)步产生的加密后的原始摘要也添加到第(3)步构建的报文中。
这个报文通过不可信任的网络传输到接收端。
(5)接受端从报文中取出原始报文,用约定的散列函数计算出摘要值,记为D1。
(6)接受端从报文中取出加密后的原始摘要,用公钥解密,还原出摘要值,记为D2。
(7)接收端比较D1和D2的值,如果相同,那么认为这个原始报文是可靠的。
实践:
我们java.security包提供了一组API 来表示数字签名的过程,这个核心类就是Signature类,它提供了一组方法来签名和验证,我们这里就给出这个类的一般用法:
我们先建立一个工具类,这个类是个单例,它主要是提供了一些封装方法来封装签名和验证的过程,因为签名和验证都需要公钥-私钥对,所以它包含了这对钥匙的产生逻辑。
package com.charles.signaturestudy;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.SignedObject;
/**** Description: 这个工具类提供了一组方法来操作Signature类,它主要可以对签名进行一些操作** @author charles.wang* @created Oct 28, 2013 11:11:52 AM**/
public class SignatureUtil {private static SignatureUtil instance = null;//公钥私钥对private KeyPair keyPair = null;//数字签名类private Signature signature = null;/*** 私有构造器,用指定的算法来初始化Signature类* @param algorithm*/private SignatureUtil(String algorithm) {try {// 实例化KeyPairGenerator对象,并且指定算法为DSAKeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);// 初始化 KeyPairGenerator对象keyPairGenerator.initialize(1024);// 生成Keypair对象keyPair = keyPairGenerator.generateKeyPair();// 实例化Signature对象,这个对象提供一组动作方法类操作签名signature = Signature.getInstance(keyPairGenerator.getAlgorithm());} catch (NoSuchAlgorithmException ex) {keyPair = null;signature = null;}}/*** 单例的工厂方法,用于创建SignatureUtil的实例** @return*/public static SignatureUtil getInstance(String algorithm) {if (instance == null)instance = new SignatureUtil(algorithm);return instance;}/*** 用私钥对指定的原始数据进行签名* @param data 被签名的数据* @return*/public byte[] signWithPrivateKey(byte[] data) {try {// 私钥完成签名,所以这里用私钥初始化用于签名的Signaturesignature.initSign(keyPair.getPrivate());// 更新要签名的原始数据signature.update(data);// 返回签名的内容return signature.sign();} catch (InvalidKeyException ie) {ie.printStackTrace();return null;} catch (SignatureException se) {se.printStackTrace();return null;}}/*** 用公钥对指定的原始数据和签名进行验证* @param data* @param sign* @return*/public boolean verifySignedObjectWithPublicKey(byte[] data, byte[] sign) {try {// 公钥完成验证,所以这里用公钥初始化用于验证的Signaturesignature.initVerify(keyPair.getPublic());// 更新要验证的原始数据signature.update(data);// 验证签名,获得验证结果return signature.verify(sign);} catch (InvalidKeyException ie) {ie.printStackTrace();return false;} catch (SignatureException se) {se.printStackTrace();return false;}}}
然后我们提供了一个演示类,它的过程如下:
先给出原始数据,再用我们的API对其进行数字签名(sign),并且打印出数字签名的内容,然后我们用我们的API来验证(verify)数字签名的有效性。
package com.charles.signaturestudy;
/**** Description: 这个类用来演示数字签名的使用方法** @author charles.wang* @created Oct 28, 2013 10:37:32 AM**/
public class SignatureDemo {public static void main(String [] args) throws Exception{//SignatureUtil是我们开发的一组动作类,它对于Signature类进行了进一步的封装//它提供了我们可以对数字签名完成的一组动作SignatureUtil sigUtil = SignatureUtil.getInstance("DSA");//原始数据对象String content="被测试的原始数据对象";//打印出原始数据System.out.println("原始数据为:"+content);//将原始数据对象转为字节数组byte[] rawData = content.getBytes();System.out.println("\n开始对原始数据签名...");//进行签名,返回签名的内容byte[] sign = sigUtil.signWithPrivateKey(rawData);System.out.println("签名内容(16进制)为:"+byte2hex(sign));System.out.println("\n开始对签名内容验证...");//进行验证,对验证结果进行分析boolean status = sigUtil.verifySignedObjectWithPublicKey(rawData, sign);if(status==true){System.out.println("验证结果,此签名是有效的");}else{System.out.println("验证结果,此签名是无效的");}}/*** 将二进制转为字符串的形式** @param b* @return*/protected static String byte2hex(byte[] b) // 二行制转字符串{// 最终要转化的16进制字符串StringBuilder hexString = new StringBuilder();// 处理每个转化的当前字符串String tmpStr = "";for (int n = 0; n < b.length; n++) {// 将二进制转为16进制tmpStr = (Integer.toHexString(b[n] & 0XFF));// 如果当前转成的字符串只有一位长度的话,则前面补0,然后加上当前转换值if (tmpStr.length() == 1) {hexString.append("0").append(tmpStr);}// 否则,,则直接将当前转换值tmpStr附加在hexString后面elsehexString.append(tmpStr);// 如果没有到byte[]的尾部,则中间用冒号分开,最后一个后面不用加冒号if (n < b.length - 1)hexString.append(":");}return hexString.toString().toUpperCase();}
}
最后,我们运行这个实例程序,然后可以清晰的看出以上的过程:
转载于:https://blog.51cto.com/supercharles888/1316192
相关文章:
C++11中shared_ptr的使用
在C中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对对象进行初始化;delete,接受一个动态对象的指针,销毁该对象,…

colly源码学习
colly源码学习 colly是一个golang写的网络爬虫。它使用起来非常顺手。看了一下它的源码,质量也是非常好的。本文就阅读一下它的源码。 使用示例 func main() {c : colly.NewCollector()// Find and visit all linksc.OnHTML("a[href]", func(e *colly.HTM…

可惜了,你们只看到“双马会”大型尬聊
作者 | 夕颜出品 | AI科技大本营(ID:rgznai100)导读:2019 年 8 月 29 日,世界人工智能大会(WAIC)在上海正式拉开帷幕。开幕式上,最让人瞩目的莫过于阿里巴巴前 CEO 马云与特斯拉 CEO Elon Musk …

Java 过滤特殊字符的 正则表达式
Java正则表达式学习: 因为正则表达式是一个很庞杂的体系,此例仅举些入门的概念,更多的请参阅相关书籍及自行摸索。 \\ 反斜杠 \t 间隔 (\u0009) \n 换行 (\u000A) \r 回车 (\u000D) \d 数字 等价于[0-9] \D 非数字 等价于[^0-9] \s 空…
C++11中unique_ptr的使用
在C中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对对象进行初始化;delete,接受一个动态对象的指针,销毁该对象,…

从这篇YouTube论文,剖析强化学习在工业级场景推荐系统中的应用
作者 | 吴海波转载自知乎用户吴海波【导读】本文作者根据两篇工业界背景的论文解答了 RL 在推荐场景需要解决的问题与困难,以及入门需要学习得相关知识点。2 个月前,业界开始流传 youtube 成功将 RL 应用在了推荐场景,并且演讲者在视频中说是…

java中两个Integer类型的值相比较的问题
转载自: https://www.cnblogs.com/xh0102/p/5280032.html 两个Integer类型整数进行比较时,一定要先用intValue()方法将其转换为int数之后再进行比较,因为直接使用比较两个Integer会出现问题。 总结: 当给Integer直接赋值时&#x…

C#共享内存实例 附源码
原文 C#共享内存实例 附源码 网上有C#共享内存类,不过功能太简单了,并且写内存每次都从开头写。故对此进行了改进,并做了个小例子,供需要的人参考。 主要改进点: 通过利用共享内存的一部分空间(以下称为“数据信息区”…
C++11中weak_ptr的使用
在C中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对对象进行初始化;delete,接受一个动态对象的指针,销毁该对象,…

经典不过时,回顾DeepCompression神经网络压缩
作者 | 薰风初入弦转载自知乎导读:本文作者为我们详细讲述了 ICLR 2016 的最佳论文 Deep Compression 中介绍的神经网络压缩方法。神经网络压缩一直是一个重要的研究方向,而目前业界最认可的压缩方法莫过于 ICLR 2016 的最佳论文 Deep Compression&#…

区块链技术特点之去中心化特性
想知道更多关于区块链技术知识,请百度【链客区块链技术问答社区】 链客,有问必答!! 由于区块链技术去中心化的特性,其在我们生活中的很多重要领域(如金融、管理)等方面具有重要的意义。例如&…

Android APK反编译
转自:http://blog.csdn.net/ithomer/article/details/6727581 一、Apk反编译得到Java源代码 下载上述反编译工具包,打开apk2java目录下的dex2jar-0.0.9.9文件夹,内含apk反编译成java源码工具,以及源码查看工具。 apk反编译工具dex…
Java泛型进阶 - 如何取出泛型类型参数
在JDK5引入了泛型特性之后,她迅速地成为Java编程中不可或缺的元素。然而,就跟泛型乍一看似乎非常容易一样,许多开发者也非常容易就迷失在这项特性里。多数Java开发者都会注意到Java编译器的类型擦除实现方式,Type Erasure会导致关…

C++11中override的使用
override是C11中的一个继承控制关键字。override确保在派生类中声明的重载函数跟基类的虚函数有相同的声明。 override明确地表示一个函数是对基类中一个虚函数的重载。更重要的是,它会检查基类虚函数和派生类中重载函数的签名不匹配问题。如果签名不匹配ÿ…

平头哥发布一站式芯片设计平台“无剑”,芯片设计成本降低50%
导读:8 月 29 日,在上海举行的世界人工智能大会上,阿里巴巴旗下半导体公司平头哥发布 SoC 芯片平台“无剑”。无剑是面向 AIoT 时代的一站式芯片设计平台,提供集芯片架构、基础软件、算法与开发工具于一体的整体解决方案ÿ…

Windows XP下,JDK环境变量配置
2019独角兽企业重金招聘Python工程师标准>>> 1.安装JDK,安装过程中可以自定义安装目录等信息,例如我们选择安装目录为D:\java\jdk1.5.0_08; 2.安装完成后,右击“我的电脑”,点击“属性”; 3.选择…

Markdown语法简介
Markdown是一种方便记忆、书写的纯文本标记语言,用户可以使用这些标记符号以最小的输入代价生成极富表现力的文档。它目标是实现易读易写。Markdown的语法全由一些符号所组成。Markdown语法的目标是成为一种适用于网络的书写语言。 Markdown优点:纯文本…

吴恩达:AI未来将呈现四大发展趋势
作者 | 夕颜出品 | AI科技大本营(ID:rgznai100)导读:8 月 30 日,世界人工智能大会精彩继续。在今天的全球工业智能峰会上,Landing.AI 创始人及首席执行官吴恩达来到现场,做了题为《人工智能是新电力》的演讲…

嵌入式课程安排 嵌入式培训课程大纲参考
嵌入式是一门综合性的学科,现在学习嵌入式开发不是单纯局限于单片机或者Linux,嵌入式课程中包含着非常多的内容。以粤嵌嵌入式课程进行参考,看看我们要学习嵌入式的话,要掌握哪些必备的技能。嵌入式课程安排包含:1、入…

Linux网站架构系列之Apache----进阶篇
本篇博文为Linux网站架构系列之apache的第二篇,我将带大家一起学习apache的编译参数,目录结构和配置文件等方面的知识,实现对apache服务的进一步掌握,并使之能更好的应用到生产实战中去。一、编译参数在上篇的apache部署中&#x…

仅用10天设计的JavaScript,凭什么成为程序员最受欢迎的编程语言?
导语:在这个世纪之交诞生的 JavaScript,没人想到会发展为当今世界上最流行的语言之一。它不够成熟,不够严肃,甚至连名字都是模仿的 Java。那么,JavaScript 的成功是依靠运气和完美时机的侥幸吗?其实不然——…

C++11中= delete;的使用
C11中,对于deleted函数,编译器会对其禁用,从而避免某些非法的函数调用或者类型转换,从而提高代码的安全性。 对于 C 的类,如果程序员没有为其定义特殊成员函数,那么在需要用到某个特殊成员函数的时候&…

vue 使用scss
使用vue-cli模板创建的项目中,使用scss步骤 1. cmd命令: cnpm install sass-loader --save-devcnpm install node-sass --sava-dev2.查看package.json文件中是否已自动添加以下信息 3. 转载于:https://www.cnblogs.com/duanzhenzhen/p/10453495.html

EBS form日历可选范围设置(calendar.setup )介绍
Calendar是Template提供给我们的standard object.可以使我们方便的为日期型字段提供日期的选择列表.form中设置日历方法:1. 为日期型字段指定LOV(ENABLE_LIST_LAMP)2. 在字段的KEY–LISTVAL事件中编写代码:Calendar.showCalendar Package包含如下几个Procedure:1. Calendar.sho…

人工智能对地球环境科学的推进
一项德国耶拿[1]和汉堡[2]科学家在《自然》杂志发起的研究表明,人工智能可以有效地推进我们对于地球气候系统的理解。特别是在当前深度学习的潜力还未被完全开发的情况下。在人工智能的帮助下一些复杂的动态环境,如飓风,森林火灾,…

从概念到应用,终于有人把数据挖掘讲明白了
作者:陈封能(Pang-Ning Tan)、迈克尔斯坦巴赫(Michael Steinbach)等来源 | 大数据(ID: hzdashuju)【导语】数据采集和存储技术的迅速发展,加之数据生成与传播的便捷性&am…

C++11中default的使用
在C11中,对于defaulted函数,编译器会为其自动生成默认的函数定义体,从而获得更高的代码执行效率,也可免除程序员手动定义该函数的工作量。 C的类有四类特殊成员函数,它们分别是:默认构造函数、析构函数、拷…

Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应...
杂家前文Android颜色对照表只有颜色和十六进制,有时候需要设置r g b分量的int值,如paint.setARGB(255, 127, 255, 212);就需要自己计算下分量的各个值。这里提供一个带有r g b分量的int型的颜色表。注意paint.setAlpha()及paint.setARGB(&…

【redis】c/c++操作redis(对于hiredis的封装)
前言 最近一直在学习redis,通过c/cpp来执行redis命令,使用的是hiredis客户端来实现的。 先简单贴一下代码 头文件 #include <vector> #include <string> #include <hiredis/hiredis.h> typedef enum en_redisResultType {redis_reply_…
OpenCV代码提取:transpose函数的实现
OpenCV中的transpose函数实现图像转置,公式为:目前fbc_cv库中也实现了transpose函数,支持多通道,uchar和float两种数据类型,经测试,与OpenCV3.1结果完全一致。实现代码transpose.hpp:// fbc_cv …