Hi! I’m struggling to select a compact equivalent C implementation of std.crypto.sign.Ed25519 to be compatible in the sense of checking message sig.
Compiling a zig’s implementation into a static lib (event with ReleaseSmall opt) is not an option - it does not fit my constraints to my regret
Are there any compatible C impls. around?
Have you checked Monocypher?
It is small-ish single file crypto implementation.
I’m not sure I understand what this means. If it is the same curve what problem you get with other implementation?
Thank you! right now I’m testing it )) I tried libsodium and wolfssl, but they didn’t work… May be I do something wrong as soon as I’m not an expert in cryptography.
I have signed a “combined” message, such as
signer.update(&optionsSlice);
signer.update(&licenseTextHash);
signer.update(&metaHash);
const signature = signer.finalize();
and then I failed to verifiy sig, given pub key, signature and input slices…
UPD. Of course, zig’s implementation works as expected, by libsodium and wolfssl did not
UPD2. When I was checking monochypher’s bindings, I discovered a “footgun” (mistake) in my code, and fixing it had reveled, that libsodium implementation was also fully compatible. As for the wolfssl I lost my patience, so it remains unclear, whether it compatible or not, my gues - yes.
As I undestand, monocypher uses blake2 hashing when verifying, while zig’s implementation sha512… Am I wrong, that this will be an issue?
Ed25519 :
The crypto_ed25519_sign() and crypto_ed25519_check() functions provide Ed25519 public key signatures and verification with SHA-512 as the underlying hash function. They are interoperable with other Ed25519 implementations.
hmmm… it looks like I have missed, that there are two implementations… and SHA512 is an optional one. It looks better!
I believe you have been confused with EdDSA. They are not the same, although it’s easy to misdirect them
The following example proves that implementations are interoperable.
const std = @import("std");
const crypto = std.crypto;
const Ed25519 = crypto.sign.Ed25519;
const SecretKey = Ed25519.SecretKey;
const KeyPair = Ed25519.KeyPair;
const mc = @cImport(
@cInclude("monocypher-ed25519.h"),
);
pub fn main() !void {
var seed: [KeyPair.seed_length]u8 = undefined;
crypto.random.bytes(&seed);
const key_pair = try KeyPair.create(seed);
var signer = try key_pair.signer(null);
signer.update("hello");
signer.update(" ");
signer.update("world");
const signature = signer.finalize();
const signature_bytes = signature.toBytes();
const message: []const u8 = "hello world";
const rc = mc.crypto_ed25519_check(
&signature_bytes,
&key_pair.public_key.bytes,
message.ptr,
message.len,
);
std.debug.print("verify: {s}\n", .{if (rc == 0) "valid" else "invalid"});
}
Great! really appreciate your time for this troubleshooting, @yataro !
Thank you!