数字签名技术详解

发布时间:2025-03-27 13:11

数字签名与加密基础知识 #生活技巧# #工作学习技巧# #数字技能培养#



签名认证是对非对称加密技术与数字摘要技术的综合运用,指的是将通信内容的摘要信息使用发送者的私钥进行加密,然后将密文与原文一起传输给信息的接收者,接收者通过发送者的公钥信息来解密被加密的摘要作息,然后使用与发送者相同的摘要算法,对接收到的内容采用相同的方式方式产生摘要串,与解密的摘要串进行对比,如果相同,则说明接收到的内容是完整的,在传输过程中没有受到第三方的篡改,否则说明通信内容已被第三方修改。

我们知道,每个人都有其特有的私钥,且都是对外界保密的,而通过私钥加密的信息,只能通过其对应的公钥来进行解密。因此,私钥可以代表私钥持有者的身份,可以通过私钥对应的公钥来对私钥拥有者的身份进行校验。通过数字签名,能够确认消息是消息发送方签名并发送过来的,因为其他人根本假冒不了消息发送方的签名,他们没有消息发送者的私钥。而不同的内容,摘要信息千差万别,通过数字摘要算法,可以确保传输内容的完整性,如果传输内容在中途被篡改了,对应的数字签名的值也将发生改变。

数字签名的产生过程如图如示:

数字签名的校验过程:

区别于不同的摘要算法,不同的非对称加密方式,数字签名的算法也不尽相同。以下为MD5withRSA和SHA1withRSA的例子。

packagecom.eudi.encode;

importjava.security.MessageDigest;

importjava.security.PrivateKey;

importjava.security.PublicKey;

importjavax.crypto.Cipher;

importsun.misc.BASE64Encoder;

publicclass MD5withRSA

{

publicstatic void main( String[] args ) throwsException

{

String content = "我是中国人,我爱自己的祖国";

RSA rsa = newRSA();

PublicKey publicKey = rsa.getPublicKey();

PrivateKey privateKey = rsa.getPrivateKey();

byte[] mysign = sign(content.getBytes(), privateKey);

booleanresult = verify(content.getBytes(), mysign, publicKey);

if(result) {

System.out.println("验证成功,数据没有被修改!");

}else{

System.out.println("验证失败,数据被修改过!");

}

}

privatestatic boolean verify(byte[] contentBytes, byte[] mysign,

PublicKey publicKey) throwsException {

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.DECRYPT_MODE, publicKey);

byte[] decrytBytes = cipher.doFinal(mysign);

MessageDigest md = MessageDigest.getInstance("MD5");

byte[] srcBytes = md.digest(contentBytes);

if(encryptBASE64(decrytBytes).equals(encryptBASE64(srcBytes))) {

System.out.println("验证成功,传送的内容为:"+ newString(contentBytes));

returntrue;

}else{

returnfalse;

}

}

privatestatic byte[] sign(byte[] conentBytes, PrivateKey privateKey) throwsException {

MessageDigest md = MessageDigest.getInstance("MD5");

byte[] md5Bytes = md.digest(conentBytes);

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.ENCRYPT_MODE, privateKey);

byte[] encrytBytes = cipher.doFinal(md5Bytes);

returnencrytBytes;

}

privatestatic String encryptBASE64(byte[] bytes) {

BASE64Encoder encoder = newBASE64Encoder();

returnencoder.encodeBuffer(bytes);

}

}

packagecom.eudi.encode;

importjava.security.KeyPair;

importjava.security.KeyPairGenerator;

importjava.security.PrivateKey;

importjava.security.PublicKey;

publicclass RSA {

privateKeyPair keyPair;

publicRSA() throwsException{

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");

keyPairGenerator.initialize(1024);

keyPair = keyPairGenerator.generateKeyPair();

}

publicPublicKey getPublicKey() {

returnkeyPair.getPublic();

}

publicPrivateKey getPrivateKey() {

returnkeyPair.getPrivate();

}

}

运行结果

验证成功,传送的内容为:我是中国人,我爱自己的祖国

验证成功,数据没有被修改!

以下是SHAwithRSA签名例子

packagecom.eudi.encode;

importjava.security.MessageDigest;

importjava.security.PrivateKey;

importjava.security.PublicKey;

importjavax.crypto.Cipher;

importsun.misc.BASE64Encoder;

publicclass SHA1withRSA

{

publicstatic void main( String[] args ) throwsException

{

String content = "我是中国人,我爱自己的祖国";

RSA rsa = newRSA();

PublicKey publicKey = rsa.getPublicKey();

PrivateKey privateKey = rsa.getPrivateKey();

byte[] mysign = sign(content.getBytes(), privateKey);

booleanresult = verify(content.getBytes(), mysign, publicKey);

if(result) {

System.out.println("验证成功,数据没有被修改!");

}else{

System.out.println("验证失败,数据被修改过!");

}

}

privatestatic boolean verify(byte[] contentBytes, byte[] mysign,

PublicKey publicKey) throwsException {

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.DECRYPT_MODE, publicKey);

byte[] decrytBytes = cipher.doFinal(mysign);

MessageDigest md = MessageDigest.getInstance("SHA1");

byte[] srcBytes = md.digest(contentBytes);

if(encryptBASE64(decrytBytes).equals(encryptBASE64(srcBytes))) {

System.out.println("验证成功,传送的内容为:"+ newString(contentBytes));

returntrue;

}else{

returnfalse;

}

}

privatestatic byte[] sign(byte[] conentBytes, PrivateKey privateKey) throwsException {

MessageDigest md = MessageDigest.getInstance("SHA1");

byte[] rha1Bytes = md.digest(conentBytes);

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.ENCRYPT_MODE, privateKey);

byte[] encrytBytes = cipher.doFinal(rha1Bytes);

returnencrytBytes;

}

privatestatic String encryptBASE64(byte[] bytes) {

BASE64Encoder encoder = newBASE64Encoder();

returnencoder.encodeBuffer(bytes);

}

}

Java提供了比较友好的API来使用数字签名,在sign方法中,先获取MD5withRSA的一个实例,然后使用私钥对signature进行初始化,调用update传入签名内容,最后生成签名。在verify方法中,使用公钥来对signature进行初始化,调用update传入需要校验的内容,调用signature的verify方法校验签名,并返回结果。

以下是笔者的代码实现

packagecom.eudi.encode;

importjava.security.PrivateKey;

importjava.security.PublicKey;

importjava.security.Signature;

publicclass SignatureAPI

{

publicstatic void main( String[] args ) throwsException

{

String content = "我是中国人,我爱自己的祖国";

RSA rsa = newRSA();

PublicKey publicKey = rsa.getPublicKey();

PrivateKey privateKey = rsa.getPrivateKey();

byte[] mysign = sign(content.getBytes(), privateKey);

booleanresult = verify(content.getBytes(), mysign, publicKey);

if(result) {

System.out.println("验证成功,数据没有被修改!");

}else{

System.out.println("验证失败,数据被修改过!");

}

}

privatestatic boolean verify(byte[] contentBytes, byte[] mysign,

PublicKey publicKey) throwsException {

Signature signature = Signature.getInstance("MD5withRSA");

signature.initVerify(publicKey);

signature.update(contentBytes);

returnsignature.verify(mysign);

}

privatestatic byte[] sign(byte[] conentBytes, PrivateKey privateKey) throwsException {

Signature signature = Signature.getInstance("MD5withRSA");

signature.initSign(privateKey);

signature.update(conentBytes);

returnsignature.sign();

}

}

还有另一种利用其他加密类进行的数字签名 我以为一并展示出来

public class DigitalSignatureTest2 {

public static void main(String args[]) throws Exception {

String content = "我是中国人,我爱自己的祖国";

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");

keyPairGenerator.initialize(1024);

KeyPair keyPair = keyPairGenerator.generateKeyPair();

RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();

RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

byte[] mysign=sign(content.getBytes(),rsaPrivateKey);

boolean result = verify(content.getBytes(), mysign, rsaPublicKey);

if(result) {

System.out.println("验证成功,数据没有被修改!");

}else {

System.out.println("验证失败,数据被修改过!");

}

}

private static byte[] sign(byte[] conentBytes, RSAPrivateKey rsaPrivateKey) throws Exception {

PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());

KeyFactory keyFactory=KeyFactory.getInstance("RSA");

PrivateKey privateKey=keyFactory.generatePrivate(pkcs8EncodedKeySpec);

Signature signature=Signature.getInstance("MD5withRSA");

signature.initSign(privateKey);

signature.update(conentBytes);

byte[] result=signature.sign();

System.out.println("私钥加密的数字签名"+ Hex.encodeHexString(result));

return result;

}

private static boolean verify(byte[] contentBytes, byte[] mysign,

RSAPublicKey rsaPublicKey) throws Exception {

X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

Signature signature = Signature.getInstance("MD5withRSA");

signature.initVerify(publicKey);

signature.update(contentBytes);

boolean bool = signature.verify(mysign);

return bool;

}

}

网址:数字签名技术详解 https://www.yuejiaxmz.com/news/view/837897

相关内容

复制的数字签名
生活垃圾艺术字签名
数字签名的应用实例
wps电子签名
数字支付的数据安全与隐私保护:最新技术和实践1.背景介绍 随着互联网和数字技术的发展,数字支付已经成为人们日常生活中不可
数据安全的实践技巧:提高安全性能1.背景介绍 数据安全是在当今数字时代中非常重要的问题。随着数据的增长和数字技术的发展,
标签解读|食品营养标签详解
盘点数字人民币中的安全技术
天翼数字生活科技有限公司内部数字化转型技术咨询项目比选公告
详解HTML标签属性linkrel='dns

随便看看