You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用BouncyCastle实现Ed25519 pureEdDSA无哈希签名?

解决方案

BouncyCastle提供的标准"ed25519"签名算法严格遵循RFC 8032规范,会默认对消息执行SHA-512哈希后再进行签名。如果要匹配你的嵌入式控制器要求的无哈希pureEdDSA逻辑,需要绕过BouncyCastle的自动哈希流程,手动实现签名逻辑。

实现步骤

1. 转换私钥格式

首先将Java标准的Ed25519PrivateKey转换为BouncyCastle底层的Ed25519PrivateKeyParameters,以便调用底层签名API:

import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters
import java.security.KeyFactory
import java.security.spec.PKCS8EncodedKeySpec

// 转换Java私钥为BouncyCastle参数类
val keyFactory = KeyFactory.getInstance("Ed25519", "BC")
val privateKeySpec = PKCS8EncodedKeySpec(privateKey.encoded)
val bcPrivateKey = keyFactory.generatePrivate(privateKeySpec) as Ed25519PrivateKeyParameters

2. 自定义无哈希签名逻辑

由于BouncyCastle的Ed25519Signer硬编码了SHA-512哈希步骤,我们可以通过反射替换哈希实现,让签名器直接使用原始消息(填充至64字节,匹配SHA-512输出长度)进行计算:

import org.bouncycastle.crypto.Digest
import org.bouncycastle.crypto.signers.Ed25519Signer
import java.lang.reflect.Field
import java.util.Arrays

// 自定义Digest,直接返回原始消息(补零至64字节),跳过哈希
class NoHashDigest : Digest {
    private val buffer = ByteArray(64)
    private var position = 0

    override fun getAlgorithmName(): String = "NoHash"
    override fun getDigestSize(): Int = 64

    override fun update(inByte: Byte) {
        if (position < 64) {
            buffer[position++] = inByte
        }
    }

    override fun update(input: ByteArray, inOff: Int, length: Int) {
        val copyLength = minOf(length, 64 - position)
        System.arraycopy(input, inOff, buffer, position, copyLength)
        position += copyLength
    }

    override fun reset() {
        position = 0
        Arrays.fill(buffer, 0x00)
    }

    override fun out(output: ByteArray, outOff: Int): Int {
        System.arraycopy(buffer, 0, output, outOff, 64)
        reset()
        return 64
    }
}

// 实例化签名器并替换哈希实现
val signer = Ed25519Signer()
val digestField: Field = Ed25519Signer::class.java.getDeclaredField("digest")
digestField.isAccessible = true
digestField.set(signer, NoHashDigest())

// 初始化签名器并生成签名
signer.init(true, bcPrivateKey)
val message = byteArrayOf(...) // 你的32字节消息
signer.update(message, 0, message.size)
val signature = signer.generateSignature() // 64字节签名

3. 注意事项

  • 这种实现属于非标准Ed25519变种,仅为匹配嵌入式控制器逻辑,不兼容标准Ed25519验证。
  • 如果控制器对消息的填充方式不是补零(比如重复消息至64字节),需要调整NoHashDigest的逻辑以匹配。

内容的提问来源于stack exchange,提问作者Raynigon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:50:57