Java安全之数字签名

数字签名能够验证数据完整性、认证数据来源,并起到抗否认的作用,这3点与OSI参考模型中的数据完整性服务、认证(鉴别)服务和抗否认性服务相对应。消息摘要算法是验证数据完整性的最佳算法,因此,该算法成为数字签名中的必要组成部分。

基于数据完整性验证,我们希望数据的发送方可以对自己所发送的数据做相应的签名处理,同时给出对应的凭证(签名),并且数据的接收方可以验证该签名是否与数据发送方发送的数据相符。如何任何人都可以进行签名处理,那么签名就失去了验证的意义。所以,签名操作只能是由数据发送方来完成,而验证签名的操作则由数据接收方来完成。既然签名操作仅限于数据发送方,那么签名操作本身只能是基于数据发送方的某些私有信息完成的。并且,用于验证操作的相关信息是由数据发送方公布给数据接收方的。

用于签名的相关信息私有,用于验证的相关信息公开,且这两种信息必须成对出现。非对称加密中的公钥与私钥恰好满足这种关系,因此成为了数字签名中的重要元素。数字签名算法包含签名与验证两项操作,遵循“私钥签名,公钥验证”的签名/验证方式,签名时需要使用私钥和待签名数据,验证时则需要公钥、签名值和待签名验证数据,其核心算法主要是消息摘要算法。

下面就看一个Java使用数字签名的例子:

package com.xtayfjpk.security;

import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

public class SignatureTest {
	private static final String KEY_PAIR_ALGOGRITHM = "DSA";
	private static final String SIGNATURE_ALGOGRITHM = "SHA1withDSA";
	private static final String PUBLIC_KEY_PATH = "public.key";
	private static final String PRIVATE_KEY_PATH = "private.key";
	private static final String SIGNATURE_PATH = "signature.dat";

	@Test //生成公钥与私钥并保存至文件
	public void testGenerateKeyPair() throws Exception {
		KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_PAIR_ALGOGRITHM);
		KeyPair keyPair = generator.generateKeyPair();
		PublicKey publicKey = keyPair.getPublic();
		PrivateKey privateKey = keyPair.getPrivate();

		writeKey(PUBLIC_KEY_PATH, publicKey);
		writeKey(PRIVATE_KEY_PATH, privateKey);
	}

	@Test
	public void testSign() throws Exception {
		String myInfo = "我的测试信息";
		PrivateKey privateKey = PrivateKey.class.cast(readKey(PRIVATE_KEY_PATH));
		//初始化一个Signature对象,并用私钥对信息签名,JDK(7)支持的数字签名算法有很多,
		//具体可参见http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature
		Signature signature = Signature.getInstance(SIGNATURE_ALGOGRITHM);
		//私钥签名
		signature.initSign(privateKey);
		//更新待签名数据
		signature.update(myInfo.getBytes());
		//得到数字签名
		byte[] signed = signature.sign();

		//把信息和签名保存在一个文件中
		writeObjects(SIGNATURE_PATH, myInfo, signed);
	}

	@Test
	public void testVerify() throws Exception {
		PublicKey publicKey = PublicKey.class.cast(readKey(PUBLIC_KEY_PATH));

		List<Object> objects = readObjects(SIGNATURE_PATH);
		String info = String.class.cast(objects.get(0));
		byte[] signed = byte[].class.cast(objects.get(1));

		//初始化签名引擎类
		Signature signature = Signature.getInstance(SIGNATURE_ALGOGRITHM);
		//公钥用于验证签名
		signature.initVerify(publicKey);
		//更新待待签名验证数据
		signature.update(info.getBytes());
		//测试签名是否正确
		System.out.println(signature.verify(signed) ? "签名正确" : "签名错误");
	}
	public void writeKey(String path, Key key) throws Exception {
		FileOutputStream fos = new FileOutputStream(path);
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(key);
		oos.close();
	}

	public Key readKey(String path) throws Exception {
		FileInputStream fis = new FileInputStream(path);
		ObjectInputStream bis = new ObjectInputStream(fis);
		Object object = bis.readObject();
		bis.close();
		return (Key) object;
	}

	public void writeObjects(String path, Serializable... objects) throws Exception {
		if(objects!=null) {
			ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
			for(Serializable object : objects) {
				oos.writeObject(object);
			}
			oos.close();
		}
	}

	public List<Object> readObjects(String path) throws Exception {
		List<Object> objects = new ArrayList<>();
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));

		boolean flag = true;
		while(flag) {
			try {
				objects.add(ois.readObject());
			} catch (EOFException e) {
				//表示流中已无对象可读
				break;
			}
		}
		ois.close();
		return objects;
	}

}
时间: 2024-08-30 13:15:28

Java安全之数字签名的相关文章

【Java密码学】用Java数字签名提供XML安全

简介 众所周知,XML在产品和项目开发中起着非常重要的作用.通过XML文档可以获取很多信息,还可以使用XML文件进行CRUD(增加.查询.更新和删除)操作.然而值得注意的是,我们如何确保XML中的数据是来自经过认证的可信和可靠的来源.关于XML文件数据的可靠性和真实性存在很多问题.通常的情况是,开发者直接处理XML文件而不去考虑数据的可靠性.有一些情况提出了上面的所有问题.现实生活中,每当我们从邮局收到一封信件时我们如何确定这封信是来自我们的朋友?依据可能是他/她的习惯用语.用词或者邮件详细地址

Java的安全学习(包括加密,数字签名,证书和认证)

(1)消息摘要: 消息摘要(Message Digest)又称为数字摘要(Digital Digest).它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生.如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了.因此消息摘要保证了消息的完整性.       消息摘要采用单向Hash 函数将需加密的明文"摘要"成一串128bit的密文,这一串密文亦称为数字指纹(Finger Print),它有固定的长

Java的发展历史

Java自1995诞生,至今已经20多年的历史. Java的名字的来源:Java是印度尼西亚爪哇岛的英文名称,因盛产咖啡而闻名.Java语言中的许多库类名称,多与咖啡有关,如JavaBeans(咖啡豆).NetBeans(网络豆)以及ObjectBeans (对象豆)等等.SUN和JAVA的标识也正是一杯正冒着热气的咖啡.据James Gosling回忆,最初这个为TV机顶盒所设计的语言在Sun内部一直称为Green项目.我们的新语言需要一个名字.Gosling注意到自己办公室外一棵茂密的橡树O

[Java]-Java的版本演化

一.Java SE 8 Java SE 8发行于2014年3月18日,代号culture,这是一个在Java历史上的重大发布 Java SE 8 新特性: Lambda Expressions(Lambda表达式) Pipelines and Streams(管道和流) Date and Time API(日期和时间API) Default Methods(接口可以有默认方法) Type Annotations(类型注解) Nashhorn JavaScript Engine Concurren

比较C++和Java 二

26.Java内置多线程支持.你可以通过继承Thread类来创建一个新的线程(重写run()方法).互斥发生在使用synchronized关键字作为类型修饰符修饰方法的对象级别.在任一时刻,只能有一个线程访问特定对象的synchronized方法.换句话说,当进入一个synchronized方法时,首先会去对对象"上锁",这对使用该对象的其他synchronized方法也有作用,并且当退出方法时"解锁"对象.没有显式的锁:上锁和解锁都是自动的.你依旧需要自己通过创建

Java 的版本历史与特性

Java SE 8[2014-03-14发行] Lambda表达式 Pipelines和Streams Date和Time API Default方法 Type注解 Nashhorn JavaScript引擎 并发计数器 Parallel操作 移除PermGen Error TLS SNI Java Version SE 7[2011-07-28发行] switch语句块中允许以字符串作为分支条件: 在创建泛型对象时应用类型推断: 在一个语句块中捕获多种异常: 支持动态语言: 支持try-wit

Java and C++

Java内置多线程支持.你可以通过继承Thread类来创建一个新的线程(重写run()方法).互斥发生在使用synchronized关键字作为类型修饰符修饰方法的对象级别.在任一时刻,只能有一个线程访问特定对象的synchronized方法.换句话说,当进入一个synchronized方法时,首先会去对对象"上锁",这对使用该对象的其他synchronized方法也有作用,并且当退出方法时"解锁"对象.没有显式的锁:上锁和解锁都是自动的.你依旧需要自己通过创建你自己

JAVA 的 基础与程序运行

简介: 在最初是为家用电器设计的,因为其特性刚好适合于Internet,于是通过在Internet上的应用得以迅速流行,成为一种计算机语言,一个平台,一个网络计算的架构. JAVA语言是一种面向对象编程语言,类是java程序的基本构造单元,JAVA中的所有语句都出现在一个 类中.面向对象包括了两个基本概念:对象和类. JAVA是一种简单的,面向对象的,分布式的,解释的,安全的,可移植的,性能优秀的语言.它一其强安全性,平台无关性,硬件结构无关性,语言简洁,面向对象的特点,在网络编程语言中占据了无

张季跃201771010139《面向对象程序设计(java)》第一周学习总结(改)

张季跃201771010139<面向对象程序设计(java)>第一周学习总结 第一部分:课程准备部分 填写课程学习 平台注册账号, 平台名称 注册账号 博客园:www.cnblogs.com Tonma 程序设计评测:https://pintia.cn/ [email protected] 代码托管平台:https://github.com/ [email protected] 中国大学MOOC:https://www.icourse163.org/ 1987400371 以下回答是或否 是否