公钥验签的signature.verify底层方法的是怎么实现的?

    /**
     * 使用公钥验签
     *
     * @param data
     * @param sign
     * @param publicKeyStr
     * @param signMode
     * @return boolean验签结果
     */
    public static boolean verify(String data, String sign, String publicKeyStr, SignMode signMode) {
        try {
            PublicKey pubKey = getPublicKey(publicKeyStr);
            Signature signature = Signature.getInstance(signMode.getMode());
            signature.initVerify(pubKey);
            signature.update(data.getBytes());
            return signature.verify(Base64Utils.decodeToByte(sign));
        } catch (Exception e) {
            log.error("验签字符串时遇到异常", e);
        }
        return false;
    }

这个SignMode signMode 是个哈希算法:SignMode.SHA1 ,问题是,既有公钥,又有数据,还有哈希,底层的 signature.verify 是怎么操作的呢?

答:代码中,SignMode 通过 signMode.getMode() 返回的是签名算法的名称,例如 SHA1WithRSA。这个算法名称是由 Signature.getInstance() 使用的,该方法会根据提供的算法名称获取一个 Signature 对象。

在这里,Signature.getInstance(signMode.getMode()) 创建了一个特定算法的 Signature 对象,用于使用给定的公钥进行验证。

signature.update(data.getBytes()) 被调用时,该方法将提供的数据更新到 Signature 对象中,实际上是对这些数据进行哈希操作,因为签名算法通常不直接对原始数据进行签名,而是对其哈希值进行签名,以提高安全性和效率。

最后,signature.verify(Base64Utils.decodeToByte(sign)) 执行验签操作,其中包括了使用提供的公钥验证已更新的数据。这个方法会返回一个布尔值,表示验签的结果。

在底层,Signature 类使用了 Java Security Provider 中相应算法的实现。例如,对于 SHA1WithRSA,它会使用 RSA 算法以及 SHA-1 哈希算法的实现来完成签名验证的过程。这个过程涉及到使用公钥解密签名并比较哈希值等操作,确保签名的合法性和数据的完整性。

那么Signature 对象,用于使用给定的公钥进行验证。是什么验证的,就是 signature.verify的底层是怎么实现的?

Signature 对象的主要目的是提供数字签名和验证数字签名的功能。在这个上下文中,验证数字签名的过程涉及以下步骤:

  1. 初始化验证模式: 使用 signature.initVerify(pubKey) 初始化 Signature 对象为验证模式,并与给定的公钥 pubKey 相关联。

  2. 更新验证数据: 使用 signature.update(data.getBytes()) 更新 Signature 对象,将待验证的原始数据添加到对象中。通常,签名算法不直接对原始数据进行签名,而是对其进行哈希操作。这确保了对大量数据的验证更高效,同时保护了数据的完整性。

  3. 执行验证: 使用 signature.verify(Base64Utils.decodeToByte(sign)) 方法,其中包括了将 Base64 编码的签名解码为字节数组的操作。验证的底层实现通常涉及使用公钥对签名进行解密,并与已哈希的原始数据进行比较。(这个是关键)

具体的验证过程取决于使用的签名算法。以 RSA 算法为例,验证过程包括使用公钥对签名进行解密,并比较解密后的值与原始数据的哈希值。如果两者匹配,则验证成功;否则,验证失败。

在底层,Signature 类通过 Java Security Provider 提供的相关算法实现验证过程。具体的实现会涉及到复杂的数学运算,例如使用公钥对签名进行解密,生成哈希值并进行比较等。这些底层细节由 Java 运行时环境的安全提供者负责实现。

上验签代码:

/**
 * 验证签名的引擎方法,用于实际验证传入的签名数据。
 *
 * @param var1 要验证的签名数据的字节数组
 * @return 如果验证成功,返回 true;否则返回 false
 * @throws SignatureException 当签名验证过程中出现异常时抛出
 */
protected boolean engineVerify(byte[] var1) throws SignatureException {
    // 检查传入的签名数据长度是否与公钥的字节长度相匹配
    if (var1.length != RSACore.getByteLength(this.publicKey)) {
        throw new SignatureException("Signature length not correct: got " + var1.length +
                                     " but was expecting " + RSACore.getByteLength(this.publicKey));
    } else {
        // 获取消息摘要的字节数组
        byte[] var2 = this.getDigestValue();

        try {
            // 使用 RSA 算法对传入的签名数据进行解密
            byte[] var3 = RSACore.rsa(var1, this.publicKey);

            // 使用填充方案对解密后的数据进行去填充操作
            byte[] var4 = this.padding.unpad(var3);

            // 将解除填充后的数据进行签名编码解析,得到实际的签名字节数组
            byte[] var5 = decodeSignature(this.digestOID, var4);

            // 比较消息摘要和解析得到的签名是否相等
            return Arrays.equals(var2, var5);
        } catch (BadPaddingException var6) {
            // 解密填充时出现异常,验证失败
            return false;
        } catch (IOException var7) {
            // 解码签名时出现异常,抛出 SignatureException
            throw new SignatureException("Signature encoding error", var7);
        }
    }
}

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Forge.js对数据进行加密需要执行以下步骤: 1. 将需要加密的数据转换为字符串形式。 2. 创建一个RSA对象,可以通过Forge.js的`pki.publicKeyFromPem()`方法PEM格式字符串中创建。 3. 将需要加密的数据转换为Uint8Array数组类型。 4. 使用RSA对象的`encrypt()`方法对数据进行加密,得到加密后的结果。 下面是一个使用Forge.js对数据进行加密的示例代码: ```javascript const forge = require('node-forge'); // PEM格式字符串 const publicKeyPem = '-----BEGIN PUBLIC KEY-----\n' + 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsEJ3J6m4OvX5Ualgiqzq\n' + '...(此处省略内容)\n' + '-----END PUBLIC KEY-----\n'; // 需要加密的数据 const data = 'Hello, World!'; // 创建RSA对象 const publicKey = forge.pki.publicKeyFromPem(publicKeyPem); // 将数据转换为Uint8Array数组类型 const dataBytes = forge.util.encodeUtf8(data); const dataBuffer = forge.util.createBuffer(dataBytes); const dataUint8Array = new Uint8Array(dataBuffer.getBytes()); // 使用RSA对象对数据进行加密 const encrypted = publicKey.encrypt(dataUint8Array); // 将加密后的结果转换为Base64编码字符串 const encryptedBase64 = forge.util.encode64(encrypted); console.log(encryptedBase64); // 输出加密后的结果 ``` 在以上示例代码中,使用`forge.util.encodeUtf8()`方法将数据转换为UTF-8编码的字节数组,然后再使用`forge.util.createBuffer()`方法将字节数组转换为Buffer对象,最终使用`new Uint8Array()`方法将Buffer对象转换为Uint8Array数组类型。 使用RSA对象的`encrypt()`方法对数据进行加密后,得到的结果是一个字节数组类型,可以使用`forge.util.encode64()`方法将其转换为Base64编码字符串。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值