Sig nonce fix (#829)

* Update submodules

* sign fix

* copilot comment fix
This commit is contained in:
EugeneDrpc
2026-05-13 12:06:55 +02:00
committed by GitHub
parent 3c4fe8985e
commit b99b74fbe1
2 changed files with 44 additions and 2 deletions

View File

@@ -29,13 +29,18 @@ class RsaSigner(
/**
* Wrapping format: `"DSHACKLESIG/" || str(nonce) || "/" || source || "/" || hex(sha256(msg))`
*
* `nonce` carries an unsigned uint64 bit pattern (proto3 uint64 ↔ Java long).
* Format it as unsigned decimal so verifiers reconstruct the same wrap for
* nonces ≥ 2^63 — otherwise `Long.toString` emits a negative number and
* signature verification fails.
*/
fun wrapMessage(nonce: Long, message: ByteArray, source: String): String {
val sha256 = MessageDigest.getInstance("SHA-256")
val formatterMsg = StringBuilder(11 + 1 + 18 + 1 + 64 + 1 + 64)
val formatterMsg = StringBuilder(11 + 1 + 20 + 1 + 64 + 1 + 64)
formatterMsg.append(MSG_PREFIX)
.append(MSG_SEPARATOR)
.append(nonce.toString())
.append(java.lang.Long.toUnsignedString(nonce))
.append(MSG_SEPARATOR)
.append(source)
.append(MSG_SEPARATOR)

View File

@@ -50,6 +50,43 @@ class RsaSignerSpec extends Specification {
sig.keyId == 100L
}
def "Wrap nonce >= 2^63 as unsigned"() {
setup:
def signer = new RsaSigner(Stub(RSAPrivateKey), 100L)
// bit pattern of 12241848404401059555 (uint64) == -6204895669308492061 (signed Long)
def nonceBits = -6204895669308492061L
when:
def act = signer.wrapMessage(nonceBits, "test".bytes, "infura")
then:
act == "DSHACKLESIG/12241848404401059555/infura/9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
!act.contains("-")
}
def "Signed message is valid for nonce >= 2^63"() {
setup:
def result = "test".bytes
def keyGen = KeyPairGenerator.getInstance("RSA")
keyGen.initialize(2048)
def pair = keyGen.generateKeyPair()
// bit pattern of 12241848404401059555 (uint64) == -6204895669308492061 (signed Long)
def nonceBits = -6204895669308492061L
def sha256 = MessageDigest.getInstance("SHA-256")
def verifier = Signature.getInstance("SHA256withRSA", "BC")
verifier.initVerify(pair.getPublic())
verifier.update("DSHACKLESIG/12241848404401059555/infura/${Hex.encodeHexString(sha256.digest(result))}".getBytes())
def signer = new RsaSigner((pair.getPrivate() as RSAPrivateKey), 100L)
when:
def sig = signer.sign(nonceBits, result, "infura")
then:
verifier.verify(sig.value)
}
def "Signer is enabled"() {
setup:
def signer = new RsaSigner(Stub(RSAPrivateKey), 1L)