diff --git a/lib/rbnacl/signatures/ed25519/signing_key.rb b/lib/rbnacl/signatures/ed25519/signing_key.rb index bc2275d..6693ca0 100644 --- a/lib/rbnacl/signatures/ed25519/signing_key.rb +++ b/lib/rbnacl/signatures/ed25519/signing_key.rb @@ -77,7 +77,11 @@ def initialize(seed) # # @return [String] Signature as bytes def sign(message) - sign_attached(message)[0, signature_bytes] + # Force message to binary encoding to ensure [0, signature_bytes] slices by bytes not characters + # This prevents issues with UTF-8 encoded strings where multi-byte characters would cause + # incorrect signature length (e.g., 90 bytes instead of 64) + message_binary = message.b + sign_attached(message_binary)[0, signature_bytes] end # Sign a message using this key, attaching the signature to the message diff --git a/lib/rbnacl/signatures/ed25519/verify_key.rb b/lib/rbnacl/signatures/ed25519/verify_key.rb index 8282c1a..f7a5055 100644 --- a/lib/rbnacl/signatures/ed25519/verify_key.rb +++ b/lib/rbnacl/signatures/ed25519/verify_key.rb @@ -51,7 +51,10 @@ def initialize(key) def verify(signature, message) signature = signature.to_str Util.check_length(signature, signature_bytes, "signature") - verify_attached(signature + message) + # Force message to binary encoding to prevent encoding compatibility errors + # when concatenating with signature (which is always ASCII-8BIT) + message_binary = message.b + verify_attached(signature + message_binary) end # Verify a signature for a given signed message diff --git a/spec/rbnacl/signatures/ed25519/signing_key_spec.rb b/spec/rbnacl/signatures/ed25519/signing_key_spec.rb index ab54e7e..cc6d330 100644 --- a/spec/rbnacl/signatures/ed25519/signing_key_spec.rb +++ b/spec/rbnacl/signatures/ed25519/signing_key_spec.rb @@ -18,6 +18,13 @@ expect(subject.sign(message)).to eq signature end + it "signs UTF-8 encoded messages" do + utf8_message = "Björn Müller from München".dup.force_encoding("UTF-8") + signature = subject.sign(utf8_message) + expect(signature.bytesize).to eq(64) + expect(subject.verify_key.verify(signature, utf8_message)).to be true + end + it "signs messages, full version" do expect(subject.sign_attached(message)[0, RbNaCl::SigningKey.signature_bytes]).to eq signature expect(subject.sign_attached(message)[RbNaCl::SigningKey.signature_bytes, message.length]).to eq message