当前位置:首页>java>耿老师教你学Java:RSA数字签名

耿老师教你学Java:RSA数字签名

  • 2026-09-08 05:32:12
耿老师教你学Java:RSA数字签名

RSA数字签名

内容摘自《Java JDK实用编程方法和算法》
第3章-3.3
推荐阅读:
新书《Java JDK 实用编程方法与算法》出版发行

3.3 RSA数字签名

    接收方要确保收到的消息是正确的发送者,即确保消息的发送者是其声称的身份,防止假冒。数字签名可以保证一旦消息在传输过程中被篡改,接受方通过验证签名即可发现。

    数字签名作用类似现实生活中的手写签名,但它是基于复杂的密码学算法,安全性更高。生活中的手写签名容易被模仿或伪造,而破解数字签名需要极高的计算能力和技术手段。

    需要注意的是,和通常公钥、私钥的角色刚好相反:消息发送方即负责数字签名一方使用私钥签名,消息接受方负责使用公约验证签名。

1. 数字签名

    消息发送方对要发送的消息(明文)进行哈希运算,生成消息的哈希值(也称此哈希值是消息的摘要)。哈希函数会将任意长度的消息转换为固定长度的哈希值,并且不同的消息生成相同哈希值的概率极低。发送方使用自己的私钥对生成的哈希值进行加密,得到数字签名。由于私钥只有发送方拥有,所以这个签名可以证明消息是由发送方发出的。

java.security包中的Signature类的实例负责实施数字签名,

(1)使用Signature类的静态方法

static Signature getInstance(String algorithm)

返回一个Signature类的实例,例如:

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

其中参数algorithm取值"SHA256withRSA"表示使用SHA256哈希算法和RSA提供的私钥实施数字签名。

(2)Signature类的实例调用

final void initSign(PrivateKey privateKey)

方法确定所使用的私钥,例如使用RSA生成的私钥privateKey:

signature.initSign(privateKey);

(3)Signature类的实例调用下列update()方法把数据data或data的一部分添加到 Signature类的实例内部的缓冲区中(不会消除此方法已经添加到缓冲区的已有内容):

final void update(byte[] data)final void update(byte[] data, int off, int len)

(4)最后Signature类的实例调用sign()方法对其缓冲区的内容实施签名,并返回签名。例如:

byte[] signBytes = signature.sign();

2.验证签名

    接收方收的角色是客户,客户收到被签名消息后,使用发送方给的公钥验证此消息的数字签名,如果消息在传输过程中没有被篡改,就会验证成功。

    (1)使用Signature类的静态方法

static Signature getInstance(String algorithm)

返回一个Signature类的实例,例如:

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

其中参数 algorithm取值"SHA256withRSA"表示使用 SHA256 哈希算法验和RSA提供的公钥实施验证。

    (2)Signature类的实例调用

final void initVerify(PublicKey publicKey)

方法确定所使用的公钥,例如使用RSA生成的公钥publicKey:

signature.initVerify(publicKey);

(3)Signature类的实例调用下列update()方法要将要验证的原始数据添加到signature的缓冲区:

final void update(byte[] data)final void update(byte[] data, int off, int len)

(4)最后Signature类的实例调用

final boolean verify(byte[] signature)

方法验证收到的消息的数字签名,并返回一个boolean值,如果boolean值是true表示验证成功,否则验证失败。例如:
boolean isSuccess = signature.verify();
注 消息签名只是对消息实施签名,不对消息实施加密。

例子3.5给文件实施数字签名并验证文件的数字签名。

import java.security.*;import java.io.*;public class Ex3_5 {    // 生成密钥对    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");        keyPairGenerator.initialize(2048);        return keyPairGenerator.generateKeyPair();    }    // 数字签名    public static byte[] signData(File file, PrivateKey privateKey) throws Exception {        Signature signature = Signature.getInstance("SHA256withRSA");        signature.initSign(privateKey);        FileInputStream in = new FileInputStream(file);        byte []data = new byte[256];        int  n = -1;        while((n = in.read(data))!=-1){            signature.update(data,0,n);//向缓冲区怎加新内容        }        //signature对其缓冲区的内容实施数字签名        byte[] signBytes = signature.sign();        return signBytes;     }    // 验证数字签名    public static boolean verifyData(File file, byte[] signatureBytes, PublicKey publicKey) throws Exception {        Signature signature = Signature.getInstance("SHA256withRSA");        signature.initVerify(publicKey);        // 将要验证的原始数据添加到signature的缓冲区        FileInputStream in = new FileInputStream(file);        byte []data = new byte[256];        int n = -1;        while((n = in.read(data))!=-1){            signature.update(data,0,n);        }       // 验证签名        return signature.verify(signatureBytes);     }    public static void main(String[] args) {        try {            // 生成密钥对            KeyPair keyPair = generateKeyPair();            PrivateKey privateKey = keyPair.getPrivate();            PublicKey publicKey = keyPair.getPublic();            File file = new File("Ex3_5.java");            System.out.println("发送方对\'"+file.getName()+"\'进行数字签名");             // 进行签名            byte[] signature = signData(file, privateKey);            System.out.println("我的数字签名:\n " + java.util.Arrays.toString(signature));            System.out.println("接受方收到\'"+file.getName()+"\'进行验证");            // 验证文件签名            boolean isValid = verifyData(file, signature, publicKey);            System.out.println("签名验证结果: " + isValid);            file = new File("Ex3_4.java");            System.out.println("接受方收到\'"+file.getName()+"\'进行验证:");            // 验证文件签名            isValid = verifyData(file, signature, publicKey);            System.out.println("签名验证结果: " + isValid);        } catch (Exception e) {            e.printStackTrace();        }    }}

最新文章

随机文章