Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion crypto/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,14 @@ func (id *Identity) Sign(message []byte) []byte {
return ed25519.Sign(id.PrivateKey, message)
}

// Verify checks a signature against the public key.
// Verify checks a signature against the public key. A public key that is not
// exactly ed25519.PublicKeySize bytes is rejected rather than passed to
// ed25519.Verify, which panics on a wrong-length key — an attacker-supplied
// key reaches this from unauthenticated message paths.
func Verify(publicKey ed25519.PublicKey, message, signature []byte) bool {
if len(publicKey) != ed25519.PublicKeySize {
return false
}
return ed25519.Verify(publicKey, message, signature)
}

Expand Down
35 changes: 35 additions & 0 deletions crypto/zz_verify_badkey_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

package crypto

import (
"crypto/ed25519"
"testing"
)

func TestVerifyRejectsWrongLengthKeyWithoutPanic(t *testing.T) {
id, err := GenerateIdentity()
if err != nil {
t.Fatal(err)
}
msg := []byte("challenge")
sig := id.Sign(msg)

for _, n := range []int{0, 1, 5, 31, 33, 64} {
bad := make([]byte, n)
if Verify(bad, msg, sig) {
t.Fatalf("Verify accepted a %d-byte public key", n)
}
}

if Verify(nil, msg, sig) {
t.Fatal("Verify accepted a nil public key")
}

if !Verify(id.PublicKey, msg, sig) {
t.Fatal("Verify rejected a valid signature")
}
if len(id.PublicKey) != ed25519.PublicKeySize {
t.Fatalf("unexpected key size %d", len(id.PublicKey))
}
}
Loading