I need to sign a 32byte message with an Ed25519PrivateKey. The signed message is verified by an embedded controller. Therefore, I need to match the implementation of this controller. The requirement is, that the 32 byte message should result in a 64 byte signature. So far so good, but the embedded controller wants to use pureEdDSA. As far as I understood the pureEdDSA generates a signature without hashing the message first. All Bouncycastle implementations I could find, are hashing the message with SHA-512 and are signing them afterwards.
Could somebody show me, how to sign the 32Byte Message without hashing it first?
What I currently have is the following code, which generates a 64 byte signature, but it is different from the one the controller expects:
val signatureProvider: Signature = Signature.getInstance("ed25519", "BC")
// Init the provider with the private key
signatureProvider.initSign(privateKey)
// Get the message as byteArray with 32 bytes
val message = byteArrayOf(...)
// Update the provider with the message
signatureProvider.update(message)
// Create signature, which is a 64Byte array
val signature = signatureProvider.sign()
That looks to me like a misunderstanding. For Ed25519 (which forms PureEdDSA with Ed448), hashing with SHA-512 is an integral part of the algorithm. More precisely, as described in RFC 8032, it is even hashed in two places with SHA-512, see steps 2 and 4 in 5.1.6. Sign (note that for PureEdDSA PH
is the identity function, so that PH(M) = M
, see 3. EdDSA Algorithm, parameter 11).
There may be a confusion with Ed25519ph (which forms HashEdDSA with Ed448ph). Here PH
is (usually) the SHA-512 hash function, so that you can speak of a previous hashing of the message.
Incidentally, the code posted implements Ed25519, i.e. PureEdDSA. You can verify this by using test vectors from RFC8032, see 7.1 Test Vectors for Ed25519.
Note that Ed25519 is supported as of Java 15 (s. JEP 339), i.e. BouncyCastle is not absolutely necessary.
So if the result does not match the result you expected, there are other reasons for this. There may be something wrong with your data or the controller may be using a different algorithm