浅析java消息摘要与数字签名

消息摘要

算法简述

定义

它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了。因此消息摘要保证了消息的完整性。消息摘要采用单向Hash 函数将需加密的明文"摘要"成一串密文,这一串密文亦称为数字指纹(Finger Print)。它有固定的长度,且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致。这样这串摘要便可成为验证明文是否是"真身"的"指纹"了。

特点

消息摘要具有以下特点:

(1)唯一性:数据只要有一点改变,那么再通过消息摘要算法得到的摘要也会发生变化。虽然理论上有可能会发生碰撞,但是概率极其低。

(2)不可逆:消息摘要算法的密文无法被解密。

(3)不需要密钥,可使用于分布式网络。

(4)无论输入的明文有多长,计算出来的消息摘要的长度总是固定的。

原理

消息摘要,其实就是将需要摘要的数据作为参数,经过哈希函数(Hash)的计算,得到的散列值。

常用算法

消息摘要算法包括MD(Message Digest,消息摘要算法)、SHA(Secure Hash Algorithm,安全散列算法)、MAC(Message AuthenticationCode,消息认证码算法)共3大系列,常用于验证数据的完整性,是数字签名算法的核心算法。

MD5和SHA1分别是MD、SHA算法系列中最有代表性的算法。

如今,MD5已被发现有许多漏洞,从而不再安全。SHA算法比MD算法的摘要长度更长,也更加安全。

算法实现

MD5、SHA的范例

JDK中使用MD5和SHA这两种消息摘要的方式基本一致,步骤如下:

(1)初始化MessageDigest对象

(2)更新要计算的内容

(3)生成摘要

importjava.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Base64;

public class MsgDigestDemo{
 public static void main(String args[]) throws NoSuchAlgorithmException, UnsupportedEncodingException {
  String msg = "Hello World!";

  MessageDigest md5Digest = MessageDigest.getInstance("MD5");
  // 更新要计算的内容
  md5Digest.update(msg.getBytes());
  // 完成哈希计算,得到摘要
  byte[] md5Encoded = md5Digest.digest();

  MessageDigest shaDigest = MessageDigest.getInstance("SHA");
  // 更新要计算的内容
  shaDigest.update(msg.getBytes());
  // 完成哈希计算,得到摘要
  byte[] shaEncoded = shaDigest.digest();

  System.out.println("原文: " + msg);
  System.out.println("MD5摘要: " + Base64.encodeBase64URLSafeString(md5Encoded));
  System.out.println("SHA摘要: " + Base64.encodeBase64URLSafeString(shaEncoded));
 }
}

结果:

原文:Hello World!
MD5摘要: 7Qdih1MuhjZehB6Sv8UNjA
SHA摘要:Lve95gjOVATpfV8EL5X4nxwjKHE

HMAC的范例

importjavax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class HmacCoder{
 /**
  * JDK支持HmacMD5, HmacSHA1,HmacSHA256, HmacSHA384, HmacSHA512
  */
 public enum HmacTypeEn {
  HmacMD5, HmacSHA1, HmacSHA256, HmacSHA384, HmacSHA512;
 }

 public static byte[] encode(byte[] plaintext, byte[] secretKey, HmacTypeEn type) throwsException {
  SecretKeySpec keySpec = new SecretKeySpec(secretKey, type.name());
  Mac mac = Mac.getInstance(keySpec.getAlgorithm());
  mac.init(keySpec);
  return mac.doFinal(plaintext);
 }

 public static void main(String[] args) throws Exception {
  String msg = "Hello World!";
  byte[] secretKey = "Secret_Key".getBytes("UTF8");
  byte[] digest = HmacCoder.encode(msg.getBytes(), secretKey, HmacTypeEn.HmacSHA256);
  System.out.println("原文: " + msg);
  System.out.println("摘要: " + Base64.encodeBase64URLSafeString(digest));
 }
}

结果:

原文:Hello World!
摘要: b8-eUifaOJ5OUFweOoq08HbGAMsIpC3Nt-Yv-S91Yr4

数字签名

算法简述

数字签名算法可以看做是一种带有密钥的消息摘要算法,并且这种密钥包含了公钥和私钥。也就是说,数字签名算法是非对称加密算法和消息摘要算法的结合体。

特点

数字签名算法要求能够验证数据完整性、认证数据来源,并起到抗否认的作用。

原理

数字签名算法包含签名和验证两项操作,遵循私钥签名,公钥验证的方式。

签名时要使用私钥和待签名数据,验证时则需要公钥、签名值和待签名数据,其核心算法主要是消息摘要算法。

常用算法

RSA、DSA、ECDSA

算法实现

DSA的范例

数字签名有两个流程:签名和验证。

它们的前提都是要有一个公钥、密钥对。

签名

用私钥为消息计算签名

验证

用公钥验证摘要

importjava.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.apache.commons.codec.binary.Base64;

public class DsaCoder{
 public static final String KEY_ALGORITHM = "DSA";

 public enum DsaTypeEn {
  MD5withDSA, SHA1withDSA
 }

 /**
  * DSA密钥长度默认1024位。 密钥长度必须是64的整数倍,范围在512~1024之间
  */
 private static final int KEY_SIZE = 1024;

 private KeyPair keyPair;

 public DsaCoder() throws Exception {
  keyPair = initKey();
 }

 public byte[] signature(byte[] data, byte[] privateKey) throws Exception {
  PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  PrivateKey key =keyFactory.generatePrivate(keySpec);

  Signature signature = Signature.getInstance(DsaTypeEn.SHA1withDSA.name());
  signature.initSign(key);
  signature.update(data);
  return signature.sign();
 }

 public boolean verify(byte[] data, byte[] publicKey, byte[] sign) throws Exception {
  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  PublicKey key =keyFactory.generatePublic(keySpec);

  Signature signature = Signature.getInstance(DsaTypeEn.SHA1withDSA.name());
  signature.initVerify(key);
  signature.update(data);
  return signature.verify(sign);
 }

 private KeyPair initKey() throws Exception {
  // 初始化密钥对生成器
  KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  // 实例化密钥对生成器
  keyPairGen.initialize(KEY_SIZE);
  // 实例化密钥对
  return keyPairGen.genKeyPair();
 }

 public byte[] getPublicKey() {
  return keyPair.getPublic().getEncoded();
 }

 public byte[] getPrivateKey() {
  return keyPair.getPrivate().getEncoded();
 }

 public static void main(String[] args) throws Exception {
  String msg = "Hello World";
  DsaCoder dsa = new DsaCoder();
  byte[] sign = dsa.signature(msg.getBytes(), dsa.getPrivateKey());
  boolean flag = dsa.verify(msg.getBytes(), dsa.getPublicKey(), sign);
  String result = flag ? "数字签名匹配" : "数字签名不匹配";
  System.out.println("数字签名:" + Base64.encodeBase64URLSafeString(sign));
  System.out.println("验证结果:" + result);
 }
}

参考

《Core Java Volume2》

《Java加密与解密技术》

(0)

相关推荐

  • java实现的MD5摘要算法完整实例

    本文实例讲述了java实现的MD5摘要算法.分享给大家供大家参考,具体如下: package com.soufun.com; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * @author WHD */ public class MD5Test { // MD5 单向加密 pub

  • java获取手机已安装APK的签名摘要

    将APK发布到应用商店或接入第三方的SDK时,有时需要提供APK的签名摘要信息,可以通过摘要算法MD5或SHA-1来获取签名的摘要,除了获取自己的APK签名,也可以获取手机上其他已安装的APK签名,只需要传入其他APK的包名即可. private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /** 获取签名的MD

  • Java实现MD5消息摘要算法

    首先,必须要强调的一点,MD5不是加密算法,而是消息摘要算法,具有不可逆性.字符串通过MD5处理后会生成128位的二进制串.我们通常会将其转化为16进制串,用于登录密码验证. 加密算法与消息摘要算法区别: 加密算法具有相应地解密算法,通过加密算法对信息进行加密后,采用解密算法能够获取到原始数据. 采用摘要算法得到的数据是不完整的,无法反向获取到原始数据. 下面直接贴代码: import java.security.MessageDigest;//Java类库已经支持MD5消息摘要 public

  • 浅析java消息摘要与数字签名

    消息摘要 算法简述 定义 它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生.如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了.因此消息摘要保证了消息的完整性.消息摘要采用单向Hash 函数将需加密的明文"摘要"成一串密文,这一串密文亦称为数字指纹(Finger Print).它有固定的长度,且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致.这样这串摘要便可成为验证明文是否是

  • Android 安全加密:消息摘要Message Digest详解

    Android安全加密专题文章索引 Android安全加密:对称加密 Android安全加密:非对称加密 Android安全加密:消息摘要Message Digest Android安全加密:数字签名和数字证书 Android安全加密:Https编程 以上学习所有内容,对称加密.非对称加密.消息摘要.数字签名等知识都是为了理解数字证书工作原理而作为一个预备知识.数字证书是密码学里的终极武器,是人类几千年历史总结的智慧的结晶,只有在明白了数字证书工作原理后,才能理解Https 协议的安全通讯机制.

  • Java加密解密和数字签名完整代码示例

    常见的加密算法 基本的单向加密算法: BASE64严格地说,属于编码格式,而非加密算法 MD5(MessageDigestalgorithm5,信息摘要算法) SHA(SecureHashAlgorithm,安全散列算法) HMAC(HashMessageAuthenticationCode,散列消息鉴别码) 复杂的对称加密(DES.PBE).非对称加密算法: DES(DataEncryptionStandard,数据加密算法) PBE(Password-basedencryption,基于密码

  • 深入浅析java web log4j 配置及在web项目中配置Log4j的技巧

    在上篇文章给大家介绍了Java log4j详细教程,本文给大家介绍java web log4j配置及web项目中配置log4j的技巧.具体详情请看下文吧. 首先给大家提供log4j.jar下载:http://logging.apache.org/log4j/1.2/download.html 一.java web项目使用log4j 1.在web.xml文件中添加 <!-- 配置log4j --> <context-param> <param-name>webAppRoo

  • Java 信息摘要加密MD2、MD4、MD5实现详解

    对于用户数据的保密一直是各个互联网企业头疼的事,那如何防止用户的个人信息泄露呢?今天为大家介绍一种最简单的加密方式--信息摘要算法MD.它如何来保护用户的个人信息呢?其实很简单,当获得到用户的信息后,先对其进行加密,然后将加密的结果保存到数据库,这样即使被盗,用户的数据也不会丢失.下面上代码: JAVA的jdk提供了MD2和MD5的加密方式, JAVA不支持MD4的jdk加密方式,jdk的实现如下: private static void MD2_jdk(){ try { MessageDige

  • Java消息摘要算法MAC实现与应用完整示例

    本文实例讲述了Java消息摘要算法MAC实现与应用.分享给大家供大家参考,具体如下: 一 介绍 MAC:Message Authentication Code HMAC:keyed-Hash Message Authencication Code,含有密钥的散列函数算法. 融合MD.SHA MD系列:HmacMD2.HmacMD4.HmacMD5 SHA系列:HmacSHA1.HmacSHA224.HmacSHA256.HmacSHA384.HmacSHA512 应用:SecureCRT 二 参

  • 浅析java 的 static 关键字用法

    本篇浅析java中static的用法,主要五个方面:静态成员变量,静态方法,静态块,静态内部类,静态导包. 首先还是一张表格说一下静态对象和非静态对象的区别: 静态对象 非静态对象 归属 类共同具有 类的各个实例独立拥有 内存分配 内存空间上固定的 附属类分配 分配空间顺序 优先分配静态对象空间 优先分配静态对象空间,初始化也一样 1 静态变量,静态方法,静态块 静态对象,静态方法都是在原对象和方法上加上static关键字修饰,表示类可以直接调用这些,而不需要实例化后再调用.具有的好处是: 1-

  • 浅析Java编程中类和对象的定义

    1,什么是类? 答:类是客观存在的,抽象的,概念的东西. 2,什么事对象? 答:对象是具体的,实际的,代表一个事物.例如:车是一个类,汽车,自行车就是他的对象. 关于类与对象的描述:类是对象的模版,对象是类的一个个体. 3,Java中定义类的方法? class 类名 用Java语法定义人类: public class Person { } 4,对象的定义方法? 1,对象声明:类名 对象名: 2,对象创建 对象名 =  new 类名(): new作用:分配内存空间. 也可以合写为:类名 对象名 =

  • 浅析Java类和数据结构中常用的方法

    1.Object类里面常用的方法: protected Object clone()创建并返回此对象的一个副本. boolean equals(Object obj)指示其他某个对象是否与此对象"相等". protected void finalize()当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法. Class<?> getClass()返回此 Object 的运行时类. int hashCode()返回该对象的哈希码值. void notif

  • 浅析Java内存模型与垃圾回收

    1.Java内存模型 Java虚拟机在执行程序时把它管理的内存分为若干数据区域,这些数据区域分布情况如下图所示: 程序计数器:一块较小内存区域,指向当前所执行的字节码.如果线程正在执行一个Java方法,这个计数器记录正在执行的虚拟机字节码指令的地址,如果执行的是Native方法,这个计算器值为空. Java虚拟机栈:线程私有的,其生命周期和线程一致,每个方法执行时都会创建一个栈帧用于存储局部变量表.操作数栈.动态链接.方法出口等信息. 本地方法栈:与虚拟机栈功能类似,只不过虚拟机栈为虚拟机执行J

随机推荐