mirror of
https://github.com/PrivateCaptcha/PrivateCaptcha.git
synced 2026-05-05 12:31:08 -05:00
3f3c0988bf
With copilot. Merged maually due to bugs
259 lines
6.1 KiB
Go
259 lines
6.1 KiB
Go
package puzzle
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"testing"
|
|
)
|
|
|
|
func TestVerifyErrorString(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for i := VerifyError(0); i < VERIFY_ERRORS_COUNT; i++ {
|
|
name := i.String()
|
|
if name == "" {
|
|
t.Errorf("Empty string for VerifyError(%d)", i)
|
|
}
|
|
|
|
if name == "error" {
|
|
t.Errorf("Unknown VerifyError: %d", i)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestVerifyErrorStringUnknown(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Test an unknown VerifyError value
|
|
unknown := VerifyError(999)
|
|
if unknown.String() != "error" {
|
|
t.Errorf("Expected 'error' for unknown VerifyError, got %q", unknown.String())
|
|
}
|
|
}
|
|
|
|
func TestParseVerifyPayloadEmpty(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
_, err := ParseVerifyPayload[ComputePuzzle, *ComputePuzzle](ctx, []byte{})
|
|
|
|
if err != errPayloadEmpty {
|
|
t.Errorf("Expected errPayloadEmpty, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestParseVerifyPayloadWrongPartsNumber(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
testCases := []struct {
|
|
name string
|
|
payload []byte
|
|
}{
|
|
{"no_dots", []byte("nodots")},
|
|
{"one_dot", []byte("one.dot")},
|
|
{"three_dots", []byte("one.two.three.four")},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
_, err := ParseVerifyPayload[ComputePuzzle, *ComputePuzzle](ctx, tc.payload)
|
|
if err != errWrongPartsNumber {
|
|
t.Errorf("Expected errWrongPartsNumber, got %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseVerifyPayloadEmptyParts(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
testCases := []struct {
|
|
name string
|
|
payload []byte
|
|
}{
|
|
{"empty_solutions", []byte(".puzzle.signature")},
|
|
{"empty_puzzle", []byte("solutions..signature")},
|
|
{"empty_signature", []byte("solutions.puzzle.")},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
_, err := ParseVerifyPayload[ComputePuzzle, *ComputePuzzle](ctx, tc.payload)
|
|
if err != errEmptyPayloadPart {
|
|
t.Errorf("Expected errEmptyPayloadPart, got %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseVerifyPayloadInvalidBase64Puzzle(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Invalid base64 in puzzle part
|
|
payload := []byte("solutions.!@#$%invalid.signature")
|
|
_, err := ParseVerifyPayload[ComputePuzzle, *ComputePuzzle](ctx, payload)
|
|
|
|
if err == nil {
|
|
t.Error("Expected error for invalid base64 puzzle")
|
|
}
|
|
}
|
|
|
|
func TestParseVerifyPayloadInvalidBase64Signature(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Valid puzzle but invalid signature
|
|
validPuzzle := base64.StdEncoding.EncodeToString([]byte("valid puzzle data"))
|
|
payload := []byte("solutions." + validPuzzle + ".!@#$%invalid")
|
|
_, err := ParseVerifyPayload[ComputePuzzle, *ComputePuzzle](ctx, payload)
|
|
|
|
if err == nil {
|
|
t.Error("Expected error for invalid base64 signature")
|
|
}
|
|
}
|
|
|
|
func TestParseVerifyPayloadEmptyDecodedPuzzle(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Empty string encoded in base64 will decode to empty bytes
|
|
emptyB64 := base64.StdEncoding.EncodeToString([]byte{})
|
|
validSig := base64.StdEncoding.EncodeToString([]byte("sig"))
|
|
payload := []byte("solutions." + emptyB64 + "." + validSig)
|
|
|
|
// Note: base64.StdEncoding.EncodeToString([]byte{}) returns "" which when
|
|
// re-decoded gives empty bytes
|
|
_, err := ParseVerifyPayload[ComputePuzzle, *ComputePuzzle](ctx, payload)
|
|
|
|
// The second part will be empty when split, so this returns errEmptyPayloadPart
|
|
if err == nil || (err != errEmptyPayloadPart && err != errEmptyPuzzle) {
|
|
t.Errorf("Expected errEmptyPayloadPart or errEmptyPuzzle, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestParseVerifyPayloadInvalidPuzzleBytes(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Valid base64 but invalid puzzle data
|
|
invalidPuzzle := base64.StdEncoding.EncodeToString([]byte("too short"))
|
|
validSig := base64.StdEncoding.EncodeToString([]byte("valid sig bytes here"))
|
|
payload := []byte("solutions." + invalidPuzzle + "." + validSig)
|
|
|
|
_, err := ParseVerifyPayload[ComputePuzzle, *ComputePuzzle](ctx, payload)
|
|
|
|
// Should fail to unmarshal the puzzle
|
|
if err == nil {
|
|
t.Error("Expected error for invalid puzzle bytes")
|
|
}
|
|
}
|
|
|
|
func TestVerifyPayloadVerifySignatureFingerprintMismatch(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
salt := NewSalt([]byte("test-salt"))
|
|
|
|
// Create a verify payload with mismatched fingerprint
|
|
vp := &VerifyPayload{
|
|
signature: &signature{
|
|
Fingerprint: salt.Fingerprint() + 1, // Wrong fingerprint
|
|
Hash: []byte("some hash"),
|
|
},
|
|
puzzleData: []byte("puzzle data"),
|
|
}
|
|
|
|
err := vp.VerifySignature(ctx, salt, nil)
|
|
|
|
if err != ErrSignKeyMismatch {
|
|
t.Errorf("Expected ErrSignKeyMismatch, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestVerifyPayloadVerifySignatureHashMismatch(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
salt := NewSalt([]byte("test-salt"))
|
|
|
|
// Create a verify payload with correct fingerprint but wrong hash
|
|
vp := &VerifyPayload{
|
|
signature: &signature{
|
|
Fingerprint: salt.Fingerprint(),
|
|
Hash: []byte("wrong hash"),
|
|
Flags: 0, // No extra salt
|
|
},
|
|
puzzleData: []byte("puzzle data"),
|
|
}
|
|
|
|
err := vp.VerifySignature(ctx, salt, nil)
|
|
|
|
if err != errSignatureMismatch {
|
|
t.Errorf("Expected errSignatureMismatch, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestStubVerifyPayload(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
puzzle := new(ComputePuzzle)
|
|
stub := NewStubPayload(puzzle)
|
|
|
|
// Test VerifySolutions
|
|
meta, verr := stub.VerifySolutions(ctx)
|
|
if verr != TestPropertyError {
|
|
t.Errorf("Expected TestPropertyError, got %v", verr)
|
|
}
|
|
if meta == nil {
|
|
t.Error("Expected non-nil metadata")
|
|
}
|
|
|
|
// Test Puzzle
|
|
if stub.Puzzle() != puzzle {
|
|
t.Error("Puzzle() should return the same puzzle")
|
|
}
|
|
|
|
// Test NeedsExtraSalt
|
|
if stub.NeedsExtraSalt() {
|
|
t.Error("Stub should not need extra salt")
|
|
}
|
|
|
|
// Test VerifySignature
|
|
err := stub.VerifySignature(ctx, nil, nil)
|
|
if err != errStubPayload {
|
|
t.Errorf("Expected errStubPayload, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestVerifyPayloadNeedsExtraSalt(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
vp := &VerifyPayload{
|
|
signature: &signature{
|
|
Flags: flagWithExtra,
|
|
},
|
|
}
|
|
|
|
if !vp.NeedsExtraSalt() {
|
|
t.Error("Expected NeedsExtraSalt to return true")
|
|
}
|
|
|
|
vp.signature.Flags = 0
|
|
if vp.NeedsExtraSalt() {
|
|
t.Error("Expected NeedsExtraSalt to return false")
|
|
}
|
|
}
|