import std/[unittest, times, base64, json, os, tempfiles, strutils, options] import ../src/nimpak/security/signature_verifier suite "Signature Algorithm Detection": test "detect Ed25519 signature formats": check detectSignatureAlgorithm("ed25519-abc123") == SigEd25519 check detectSignatureAlgorithm("a".repeat(128)) == SigEd25519 # 128 hex chars test "detect Dilithium signature formats": expect ValueError: discard detectSignatureAlgorithm("dilithium-abc123") # Not implemented yet test "invalid signature formats": expect ValueError: discard detectSignatureAlgorithm("invalid-sig") expect ValueError: discard detectSignatureAlgorithm("abc") # Too short suite "Signature String Parsing": test "parse Ed25519 signature strings": let (alg1, sig1) = parseSignatureString("ed25519-abc123def456") check alg1 == SigEd25519 check sig1 == "abc123def456" let (alg2, sig2) = parseSignatureString("a".repeat(128)) check alg2 == SigEd25519 check sig2 == "a".repeat(128) test "format signature strings": check formatSignatureString(SigEd25519, "abc123") == "ed25519-abc123" check formatSignatureString(SigDilithium, "def456") == "dilithium-def456" check formatSignatureString(SigRSA, "789abc") == "rsa-789abc" suite "Ed25519 Signature Verification": # Test vectors for Ed25519 (RFC 8032) const ED25519_TEST_VECTORS = [ ( message: "", publicKey: "11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=", signature: "hgyY0il+MGCjP0JzlnkSPjt9HQjyOh1XBL2QX5AjXtYzOjIh2+3IfGG07fAuNqq41PvvRMzFRuV+DqbpBRlHBg==", valid: true ), ( message: "test message", publicKey: "11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=", signature: "invalid-signature-data", valid: false ) ] test "Ed25519 signature verification with test vectors": for vector in ED25519_TEST_VECTORS: let result = verifyEd25519Signature(vector.message, vector.signature, vector.publicKey) if vector.valid: check result == true else: check result == false test "Ed25519 signature with invalid inputs": # Invalid signature length check verifyEd25519Signature("test", "short", "validkey") == false # Invalid public key length check verifyEd25519Signature("test", "valid-sig", "short") == false # Invalid base64 check verifyEd25519Signature("test", "invalid-base64!", "invalid-base64!") == false suite "Signature Verifier": test "create signature verifier": let verifier = newSignatureVerifier() check verifier.trustedKeys.len == 0 check verifier.requireValidTimestamp == true check SigEd25519 in verifier.allowedAlgorithms test "add trusted key": var verifier = newSignatureVerifier() let key = createPublicKey( SigEd25519, "test-key-1", "test-key-data", now().utc() - initDuration(days = 1), now().utc() + initDuration(days = 365) ) verifier.addTrustedKey(key) check verifier.trustedKeys.len == 1 check verifier.trustedKeys[0].keyId == "test-key-1" test "find trusted key": var verifier = newSignatureVerifier() let key = createPublicKey( SigEd25519, "findable-key", "test-key-data", now().utc() - initDuration(days = 1), now().utc() + initDuration(days = 365) ) verifier.addTrustedKey(key) let foundKey = verifier.findTrustedKey("findable-key") check foundKey.isSome() check foundKey.get().keyId == "findable-key" let notFoundKey = verifier.findTrustedKey("nonexistent-key") check notFoundKey.isNone() suite "Key Validation": test "key validity checks": let now = times.now().utc() # Valid key let validKey = createPublicKey( SigEd25519, "valid-key", "key-data", now - initDuration(days = 1), now + initDuration(days = 365) ) check isKeyValid(validKey, now) == true # Expired key let expiredKey = createPublicKey( SigEd25519, "expired-key", "key-data", now - initDuration(days = 365), now - initDuration(days = 1) ) check isKeyValid(expiredKey, now) == false # Not yet valid key let futureKey = createPublicKey( SigEd25519, "future-key", "key-data", now + initDuration(days = 1), now + initDuration(days = 365) ) check isKeyValid(futureKey, now) == false # Revoked key var revokedKey = validKey revokedKey.revoked = true check isKeyValid(revokedKey, now) == false suite "Digital Signature Objects": test "create digital signature": let timestamp = now().utc() let sig = createDigitalSignature(SigEd25519, "test-key", "signature-data", timestamp) check sig.algorithm == SigEd25519 check sig.keyId == "test-key" check sig.signature == "signature-data" check sig.timestamp == timestamp test "create public key": let validFrom = now().utc() let validUntil = validFrom + initDuration(days = 365) let key = createPublicKey(SigEd25519, "test-key", "key-data", validFrom, validUntil) check key.algorithm == SigEd25519 check key.keyId == "test-key" check key.keyData == "key-data" check key.validFrom == validFrom check key.validUntil == validUntil check key.revoked == false test "signature validation": let validSig = createDigitalSignature(SigEd25519, "key-1", "sig-data") check isSignatureValid(validSig) == true let invalidSig = createDigitalSignature(SigEd25519, "", "sig-data") check isSignatureValid(invalidSig) == false let invalidSig2 = createDigitalSignature(SigEd25519, "key-1", "") check isSignatureValid(invalidSig2) == false suite "Signature Policy": test "create signature policy": let policy = newSignaturePolicy() check policy.requireSignatures == true check SigEd25519 in policy.allowedAlgorithms check policy.minimumKeySize == 256 check policy.maxSignatureAge == 86400 check policy.requireTimestamp == true check policy.allowSelfSigned == false test "validate signature against policy": let policy = newSignaturePolicy() # Valid signature let validSig = createDigitalSignature(SigEd25519, "key-1", "sig-data", now().utc()) check validateSignaturePolicy(validSig, policy) == true # Invalid algorithm let invalidAlgSig = createDigitalSignature(SigRSA, "key-1", "sig-data", now().utc()) check validateSignaturePolicy(invalidAlgSig, policy) == false # Too old signature let oldSig = createDigitalSignature(SigEd25519, "key-1", "sig-data", now().utc() - initDuration(days = 2)) check validateSignaturePolicy(oldSig, policy) == false suite "File Signature Verification": test "verify file signature": # Create a temporary file let (tempFile, tempPath) = createTempFile("nimpak_sig_test_", ".txt") tempFile.write("Test file content for signature verification") tempFile.close() try: # This test would require actual Ed25519 key generation and signing # For now, we test the error handling expect IOError: let verifier = newSignatureVerifier() let sig = createDigitalSignature(SigEd25519, "test-key", "fake-signature") discard verifier.verifyFileSignature("/nonexistent/file.txt", sig) finally: removeFile(tempPath) suite "Hybrid Signature Support": test "create hybrid signature": let classicalSig = createDigitalSignature(SigEd25519, "classical-key", "classical-sig") let quantumSig = createDigitalSignature(SigDilithium, "quantum-key", "quantum-sig") let hybridSig = HybridSignature( classicalSig: classicalSig, quantumSig: some(quantumSig), requireBoth: true ) check hybridSig.classicalSig.algorithm == SigEd25519 check hybridSig.quantumSig.isSome() check hybridSig.quantumSig.get().algorithm == SigDilithium check hybridSig.requireBoth == true suite "Signature Information": test "get signature info": let timestamp = now().utc() let sig = createDigitalSignature(SigEd25519, "info-key", "info-sig", timestamp) let info = getSignatureInfo(sig) check "ed25519" in info.toLower() check "info-key" in info check $timestamp in info suite "Error Handling": test "signature verification errors": let verifier = newSignatureVerifier() let sig = createDigitalSignature(SigEd25519, "nonexistent-key", "fake-signature") expect SignatureVerificationError: discard verifier.verifySignature("test message", sig) test "unsupported algorithm errors": expect ValueError: discard verifyDilithiumSignature("test", "sig", "key") expect ValueError: discard verifyRSASignature("test", "sig", "key") suite "Integration with Hash Verifier": test "verify hash signature": let verifier = newSignatureVerifier() let hash = "blake2b-abc123def456" let sig = createDigitalSignature(SigEd25519, "hash-key", "hash-signature") # This would fail because we don't have the trusted key expect SignatureVerificationError: discard verifier.verifyHashSignature(hash, sig) suite "Performance and Statistics": test "signature verification timing": # Create a mock signature that will fail verification let verifier = newSignatureVerifier() let sig = createDigitalSignature(SigEd25519, "timing-key", "timing-signature") expect SignatureVerificationError: let result = verifier.verifySignature("timing test", sig) # Even failed verification should have timing information check result.verificationTime >= 0.0