wycheproof
Install this skill
npx skills add trailofbits/skillsWorks across Claude Code, Cursor, Codex, Copilot & Antigravity
Wycheproof is a specialized suite of cryptographic test vectors that enables developers to validate security implementations against known attack patterns and edge-case behaviors. Originally created by Google, the project provides a structured set of JSON-based test cases for algorithms including AES-GCM, ECDSA, RSA, and various elliptic curves. By using these vectors, developers can determine if their cryptographic code handles malformed keys, invalid parameters, or edge-case input values in a secure, predictable manner. It acts as a baseline check to prevent common implementation flaws that often lead to vulnerabilities such as signature forgery or side-channel exposures. While not a substitute for formal verification or constant-time analysis, Wycheproof serves as a vital component for CI/CD pipelines to ensure cryptographic libraries conform to industry-standard expectations.
When to Use This Skill
- β’Auditing a custom implementation of an established cryptographic primitive
- β’Ensuring interoperability between different cryptographic libraries
- β’Integrating automated security regression testing into a library's CI pipeline
- β’Validating handling of malformed input data in security-critical code
How to Invoke This Skill
Example prompts that trigger this skill in Claude Code, Cursor, or Antigravity:
- βRun Wycheproof test vectors against my AES-GCM implementation
- βHow do I use Wycheproof to validate my ECDSA signature logic?
- βGenerate a test harness for the Wycheproof JSON vectors
- βCheck if my library passes standard cryptographic edge cases
- βIntegrate Wycheproof tests into the current CI build
Pro Tips
- π‘Combine with static analysis tools: Use Wycheproof results to focus your static analysis efforts on potentially vulnerable crypto implementations, creating a multi-layered security approach.
- π‘Iterate on failed tests: When a Wycheproof test fails, leverage the skill to suggest specific code adjustments, library updates, or configuration changes to rectify the issue effectively.
- π‘Automate regression testing: Integrate Wycheproof-based checks into your CI/CD pipeline to prevent regressions in cryptographic correctness and maintain ongoing security compliance.
What this skill does
- β’Provides standardized JSON test vectors for major symmetric and asymmetric algorithms
- β’Validates implementation behavior against known cryptographic attack patterns
- β’Supports fine-grained testing across different key sizes, curves, and IV lengths
- β’Enables automated compliance checking within CI/CD build cycles
- β’Distinguishes between valid, invalid, and acceptable cryptographic outputs
When not to use it
- βEvaluating timing side-channel resistance in code execution
- βFuzzing or discovering previously unknown cryptographic zero-day vulnerabilities
- βTesting experimental or non-standard cryptographic constructions
Example workflow
- Clone the Wycheproof repository as a submodule
- Select the specific JSON test file matching the algorithm under test
- Write a test harness that parses the JSON test groups and attributes
- Execute the harness to run the implementation against each tcId
- Compare the implementation results against the expected output flags
- Update the test harness if the library receives security patches
Prerequisites
- βExisting cryptographic implementation in a supported language
- βBasic knowledge of JSON parsing for test execution
- βFamiliarity with the algorithm specifications being tested
Pitfalls & limitations
- !Passing Wycheproof tests does not guarantee overall security or constant-time safety
- !It covers only established, well-known algorithms rather than custom math
- !Some test vectors require specific handling of invalid or malicious inputs that can be complex to implement correctly
FAQ
How it compares
Wycheproof provides concrete, peer-reviewed test data that prevents the errors inherent in writing test cases from memory; manual testing often misses complex edge cases like invalid curves or malformed padding.
Source & trust
π Full skill instructions β original source: trailofbits/skills
Wycheproof is an extensive collection of test vectors designed to verify the correctness of cryptographic implementations and test against known attacks. Originally developed by Google, it is now a community-managed project where contributors can add test vectors for specific cryptographic constructions.
## Background
### Key Concepts
| Concept | Description |
|---------|-------------|
| Test vector | Input/output pair for validating crypto implementation correctness |
| Test group | Collection of test vectors sharing attributes (key size, IV size, curve) |
| Result flag | Indicates if test should pass (valid), fail (invalid), or is acceptable |
| Edge case testing | Testing for known vulnerabilities and attack patterns |
### Why This Matters
Cryptographic implementations are notoriously difficult to get right. Even small bugs can:
- Expose private keys
- Allow signature forgery
- Enable message decryption
- Create consensus problems when different implementations accept/reject the same inputs
Wycheproof has found vulnerabilities in major libraries including OpenJDK's SHA1withDSA, Bouncy Castle's ECDHC, and the elliptic npm package.
## When to Use
**Apply Wycheproof when:**
- Testing cryptographic implementations (AES-GCM, ECDSA, ECDH, RSA, etc.)
- Validating that crypto code handles edge cases correctly
- Verifying implementations against known attack vectors
- Setting up CI/CD for cryptographic libraries
- Auditing third-party crypto code for correctness
**Consider alternatives when:**
- Testing for timing side-channels (use constant-time testing tools instead)
- Finding new unknown bugs (use fuzzing instead)
- Testing custom/experimental cryptographic algorithms (Wycheproof only covers established algorithms)
## Quick Reference
| Scenario | Recommended Approach | Notes |
|----------|---------------------|-------|
| AES-GCM implementation | Use
aes_gcm_test.json | 316 test vectors across 44 test groups || ECDSA verification | Use
ecdsa_*_test.json for specific curves | Tests signature malleability, DER encoding || ECDH key exchange | Use
ecdh_*_test.json | Tests invalid curve attacks || RSA signatures | Use
rsa_*_test.json | Tests padding oracle attacks || ChaCha20-Poly1305 | Use
chacha20_poly1305_test.json | Tests AEAD implementation |## Testing Workflow
Phase 1: Setup Phase 2: Parse Test Vectors
βββββββββββββββββββ βββββββββββββββββββ
β Add Wycheproof β β β Load JSON file β
β as submodule β β Filter by paramsβ
βββββββββββββββββββ βββββββββββββββββββ
β β
Phase 4: CI Integration Phase 3: Write Harness
βββββββββββββββββββ βββββββββββββββββββ
β Auto-update β β β Test valid & β
β test vectors β β invalid cases β
βββββββββββββββββββ βββββββββββββββββββ## Repository Structure
The Wycheproof repository is organized as follows:
β£ π README.md : Project overview
β£ π doc : Documentation
β£ π java : Java JCE interface testing harness
β£ π javascript : JavaScript testing harness
β£ π schemas : Test vector schemas
β£ π testvectors : Test vectors
β π testvectors_v1 : Updated test vectors (more detailed)The essential folders are
testvectors and testvectors_v1. While both contain similar files, testvectors_v1 includes more detailed information and is recommended for new integrations.## Supported Algorithms
Wycheproof provides test vectors for a wide range of cryptographic algorithms:
| Category | Algorithms |
|----------|------------|
| **Symmetric Encryption** | AES-GCM, AES-EAX, ChaCha20-Poly1305 |
| **Signatures** | ECDSA, EdDSA, RSA-PSS, RSA-PKCS1 |
| **Key Exchange** | ECDH, X25519, X448 |
| **Hashing** | HMAC, HKDF |
| **Curves** | secp256k1, secp256r1, secp384r1, secp521r1, ed25519, ed448 |
## Test File Structure
Each JSON test file tests a specific cryptographic construction. All test files share common attributes:
"algorithm" : The name of the algorithm tested
"schema" : The JSON schema (found in schemas folder)
"generatorVersion" : The version number
"numberOfTests" : The total number of test vectors in this file
"header" : Detailed description of test vectors
"notes" : In-depth explanation of flags in test vectors
"testGroups" : Array of one or multiple test groups### Test Groups
Test groups group sets of tests based on shared attributes such as:
- Key sizes
- IV sizes
- Public keys
- Curves
This classification allows extracting tests that meet specific criteria relevant to the construction being tested.
### Test Vector Attributes
#### Shared Attributes
All test vectors contain four common fields:
- **tcId**: Unique identifier for the test vector within a file
- **comment**: Additional information about the test case
- **flags**: Descriptions of specific test case types and potential dangers (referenced in
notes field)- **result**: Expected outcome of the test
The
result field can take three values:| Result | Meaning |
|--------|---------|
| **valid** | Test case should succeed |
| **acceptable** | Test case is allowed to succeed but contains non-ideal attributes |
| **invalid** | Test case should fail |
#### Unique Attributes
Unique attributes are specific to the algorithm being tested:
| Algorithm | Unique Attributes |
|-----------|-------------------|
| AES-GCM |
key, iv, aad, msg, ct, tag || ECDH secp256k1 |
public, private, shared || ECDSA |
msg, sig, result || EdDSA |
msg, sig, pk |## Implementation Guide
### Phase 1: Add Wycheproof to Your Project
**Option 1: Git Submodule (Recommended)**
Adding Wycheproof as a git submodule ensures automatic updates:
git submodule add https://github.com/C2SP/wycheproof.git**Option 2: Fetch Specific Test Vectors**
If submodules aren't possible, fetch specific JSON files:
#!/bin/bash
TMP_WYCHEPROOF_FOLDER=".wycheproof/"
TEST_VECTORS=('aes_gcm_test.json' 'aes_eax_test.json')
BASE_URL="https://raw.githubusercontent.com/C2SP/wycheproof/master/testvectors_v1/"
# Create wycheproof folder
mkdir -p $TMP_WYCHEPROOF_FOLDER
# Request all test vector files if they don't exist
for i in "${TEST_VECTORS[@]}"; do
if [ ! -f "${TMP_WYCHEPROOF_FOLDER}${i}" ]; then
curl -o "${TMP_WYCHEPROOF_FOLDER}${i}" "${BASE_URL}${i}"
if [ $? -ne 0 ]; then
echo "Failed to download ${i}"
exit 1
fi
fi
done### Phase 2: Parse Test Vectors
Identify the test file for your algorithm and parse the JSON:
**Python Example:**
import json
def load_wycheproof_test_vectors(path: str):
testVectors = []
try:
with open(path, "r") as f:
wycheproof_json = json.loads(f.read())
except FileNotFoundError:
print(f"No Wycheproof file found at: {path}")
return testVectors
# Attributes that need hex-to-bytes conversion
convert_attr = {"key", "aad", "iv", "msg", "ct", "tag"}
for testGroup in wycheproof_json["testGroups"]:
# Filter test groups based on implementation constraints
if testGroup["ivSize"] < 64 or testGroup["ivSize"] > 1024:
continue
for tv in testGroup["tests"]:
# Convert hex strings to bytes
for attr in convert_attr:
if attr in tv:
tv[attr] = bytes.fromhex(tv[attr])
testVectors.append(tv)
return testVectors**JavaScript Example:**
const fs = require('fs').promises;
async function loadWycheproofTestVectors(path) {
const tests = [];
try {
const fileContent = await fs.readFile(path);
const data = JSON.parse(fileContent.toString());
data.testGroups.forEach(testGroup => {
testGroup.tests.forEach(test => {
// Add shared test group properties to each test
test['pk'] = testGroup.publicKey.pk;
tests.push(test);
});
});
} catch (err) {
console.error('Error reading or parsing file:', err);
throw err;
}
return tests;
}### Phase 3: Write Testing Harness
Create test functions that handle both valid and invalid test cases.
**Python/pytest Example:**
import pytest
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
tvs = load_wycheproof_test_vectors("wycheproof/testvectors_v1/aes_gcm_test.json")
@pytest.mark.parametrize("tv", tvs, ids=[str(tv['tcId']) for tv in tvs])
def test_encryption(tv):
try:
aesgcm = AESGCM(tv['key'])
ct = aesgcm.encrypt(tv['iv'], tv['msg'], tv['aad'])
except ValueError as e:
# Implementation raised error - verify test was expected to fail
assert tv['result'] != 'valid', tv['comment']
return
if tv['result'] == 'valid':
assert ct[:-16] == tv['ct'], f"Ciphertext mismatch: {tv['comment']}"
assert ct[-16:] == tv['tag'], f"Tag mismatch: {tv['comment']}"
elif tv['result'] == 'invalid' or tv['result'] == 'acceptable':
assert ct[:-16] != tv['ct'] or ct[-16:] != tv['tag']
@pytest.mark.parametrize("tv", tvs, ids=[str(tv['tcId']) for tv in tvs])
def test_decryption(tv):
try:
aesgcm = AESGCM(tv['key'])
decrypted_msg = aesgcm.decrypt(tv['iv'], tv['ct'] + tv['tag'], tv['aad'])
except ValueError:
assert tv['result'] != 'valid', tv['comment']
return
except InvalidTag:
assert tv['result'] != 'valid', tv['comment']
assert 'ModifiedTag' in tv['flags'], f"Expected 'ModifiedTag' flag: {tv['comment']}"
return
assert tv['result'] == 'valid', f"No invalid test case should pass: {tv['comment']}"
assert decrypted_msg == tv['msg'], f"Decryption mismatch: {tv['comment']}"**JavaScript/Mocha Example:**
const assert = require('assert');
function testFactory(tcId, tests) {
it([${tcId + 1}] ${tests[tcId].comment}, function () {
const test = tests[tcId];
const ed25519 = new eddsa('ed25519');
const key = ed25519.keyFromPublic(toArray(test.pk, 'hex'));
let sig;
if (test.result === 'valid') {
sig = key.verify(test.msg, test.sig);
assert.equal(sig, true, [${test.tcId}] ${test.comment});
} else if (test.result === 'invalid') {
try {
sig = key.verify(test.msg, test.sig);
} catch (err) {
// Point could not be decoded
sig = false;
}
assert.equal(sig, false, [${test.tcId}] ${test.comment});
}
});
}
// Generate tests for all test vectors
for (var tcId = 0; tcId < tests.length; tcId++) {
testFactory(tcId, tests);
}### Phase 4: CI Integration
Ensure test vectors stay up to date by:
1. **Using git submodules**: Update submodule in CI before running tests
2. **Fetching latest vectors**: Run fetch script before test execution
3. **Scheduled updates**: Set up weekly/monthly updates to catch new test vectors
## Common Vulnerabilities Detected
Wycheproof test vectors are designed to catch specific vulnerability patterns:
| Vulnerability | Description | Affected Algorithms | Example CVE |
|---------------|-------------|---------------------|-------------|
| Signature malleability | Multiple valid signatures for same message | ECDSA, EdDSA | CVE-2024-42459 |
| Invalid DER encoding | Accepting non-canonical DER signatures | ECDSA | CVE-2024-42460, CVE-2024-42461 |
| Invalid curve attacks | ECDH with invalid curve points | ECDH | Common in many libraries |
| Padding oracle | Timing leaks in padding validation | RSA-PKCS1 | Historical OpenSSL issues |
| Tag forgery | Accepting modified authentication tags | AES-GCM, ChaCha20-Poly1305 | Various implementations |
### Signature Malleability: Deep Dive
**Problem:** Implementations that don't validate signature encoding can accept multiple valid signatures for the same message.
**Example (EdDSA):** Appending or removing zeros from signature:
Valid signature: ...6a5c51eb6f946b30d
Invalid signature: ...6a5c51eb6f946b30d0000 (should be rejected)**How to detect:**
# Add signature length check
if len(sig) != 128: # EdDSA signatures must be exactly 64 bytes (128 hex chars)
return False**Impact:** Can lead to consensus problems when different implementations accept/reject the same signatures.
**Related Wycheproof tests:**
- EdDSA: tcId 37 - "removing 0 byte from signature"
- ECDSA: tcId 06 - "Legacy: ASN encoding of r misses leading 0"
## Case Study: Elliptic npm Package
This case study demonstrates how Wycheproof found three CVEs in the popular elliptic npm package (3000+ dependents, millions of weekly downloads).
### Overview
The [elliptic](https://www.npmjs.com/package/elliptic) library is an elliptic-curve cryptography library written in JavaScript, supporting ECDH, ECDSA, and EdDSA. Using Wycheproof test vectors on version 6.5.6 revealed multiple vulnerabilities:
- **CVE-2024-42459**: EdDSA signature malleability (appending/removing zeros)
- **CVE-2024-42460**: ECDSA DER encoding - invalid bit placement
- **CVE-2024-42461**: ECDSA DER encoding - leading zero in length field
### Methodology
1. **Identify supported curves**: ed25519 for EdDSA
2. **Find test vectors**:
testvectors_v1/ed25519_test.json3. **Parse test vectors**: Load JSON and extract tests
4. **Write test harness**: Create parameterized tests
5. **Run tests**: Identify failures
6. **Analyze root causes**: Examine implementation code
7. **Propose fixes**: Add validation checks
### Key Findings
**EdDSA Issue (CVE-2024-42459):**
- Missing signature length validation
- Allowed trailing zeros in signatures
- Fix: Add
if(sig.length !== 128) return false;**ECDSA Issue 1 (CVE-2024-42460):**
- Missing check for first bit being zero in DER-encoded r and s values
- Fix: Add
if ((data[p.place] & 128) !== 0) return false;**ECDSA Issue 2 (CVE-2024-42461):**
- DER length field accepted leading zeros
- Fix: Add
if(buf[p.place] === 0x00) return false;### Impact
All three vulnerabilities allowed multiple valid signatures for a single message, leading to consensus problems across implementations.
**Lessons learned:**
- Wycheproof catches subtle encoding bugs
- Reusable test harnesses pay dividends
- Test vector comments and flags help diagnose issues
- Even popular libraries benefit from systematic test vector validation
## Advanced Usage
### Tips and Tricks
| Tip | Why It Helps |
|-----|--------------|
| Filter test groups by parameters | Focus on test vectors relevant to your implementation constraints |
| Use test vector flags | Understand specific vulnerability patterns being tested |
| Check the
notes field | Get detailed explanations of flag meanings || Test both encrypt/decrypt and sign/verify | Ensure bidirectional correctness |
| Run tests in CI | Catch regressions and benefit from new test vectors |
| Use parameterized tests | Get clear failure messages with tcId and comment |
### Common Mistakes
| Mistake | Why It's Wrong | Correct Approach |
|---------|----------------|------------------|
| Only testing valid cases | Misses vulnerabilities where invalid inputs are accepted | Test all result types: valid, invalid, acceptable |
| Ignoring "acceptable" result | Implementation might have subtle bugs | Treat acceptable as warnings worth investigating |
| Not filtering test groups | Wastes time on unsupported parameters | Filter by keySize, ivSize, etc. based on your implementation |
| Not updating test vectors | Miss new vulnerability patterns | Use submodules or scheduled fetches |
| Testing only one direction | Encrypt/sign might work but decrypt/verify fails | Test both operations |
## Related Skills
### Tool Skills
| Skill | Primary Use in Wycheproof Testing |
|-------|-----------------------------------|
| **pytest** | Python testing framework for parameterized tests |
| **mocha** | JavaScript testing framework for test generation |
| **constant-time-testing** | Complement Wycheproof with timing side-channel testing |
| **cryptofuzz** | Fuzz-based crypto testing to find additional bugs |
### Technique Skills
| Skill | When to Apply |
|-------|---------------|
| **coverage-analysis** | Ensure test vectors cover all code paths in crypto implementation |
| **property-based-testing** | Test mathematical properties (e.g., encrypt/decrypt round-trip) |
| **fuzz-harness-writing** | Create harnesses for crypto parsers (complements Wycheproof) |
### Related Domain Skills
| Skill | Relationship |
|-------|--------------|
| **crypto-testing** | Wycheproof is a key tool in comprehensive crypto testing methodology |
| **fuzzing** | Use fuzzing to find bugs Wycheproof doesn't cover (new edge cases) |
## Skill Dependency Map
βββββββββββββββββββββββ
β wycheproof β
β (this skill) β
ββββββββββββ¬βββββββββββ
β
βββββββββββββββββββββΌββββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β pytest/mocha β β constant-time β β cryptofuzz β
β (test framework)β β testing β β (fuzzing) β
ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ
β β β
βββββββββββββββββββββΌββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββ
β Technique Skills β
β coverage, harness, PBT β
ββββββββββββββββββββββββββββ## Resources
### Official Repository
**[Wycheproof GitHub Repository](https://github.com/C2SP/wycheproof)**
The official repository contains:
- All test vectors in
testvectors/ and testvectors_v1/- JSON schemas in
schemas/- Reference implementations in Java and JavaScript
- Documentation in
doc/### Real-World Examples
**[pycryptodome](https://pypi.org/project/pycryptodome/)**
The pycryptodome library integrates Wycheproof test vectors in their test suite, demonstrating best practices for Python crypto implementations.
### Community Resources
- [C2SP Community](https://c2sp.org/) - Cryptographic specifications and standards community maintaining Wycheproof
- Wycheproof issues tracker - Report bugs in test vectors or suggest new constructions
## Summary
Wycheproof is an essential tool for validating cryptographic implementations against known attack vectors and edge cases. By integrating Wycheproof test vectors into your testing workflow:
1. Catch subtle encoding and validation bugs
2. Prevent signature malleability issues
3. Ensure consistent behavior across implementations
4. Benefit from community-contributed test vectors
5. Protect against known cryptographic vulnerabilities
The investment in writing a reusable testing harness pays dividends through continuous validation as new test vectors are added to the Wycheproof repository.
How to Use This Skill Unit
Option A: Project-Specific (Recommended)
- Click "Download" above
- In your project, create the directory:
.agent/skills/wycheproof/ - Save the file as
SKILL.md - The agent will automatically discover the skill based on its description.
Option B: Global Installation (All Agents)
Save the file to these locations to make it available across all projects:
- Claude Code:
~/.claude/skills/trailofbits/skills/wycheproof/SKILL.md - Cursor:
~/.cursor/skills/trailofbits/skills/wycheproof/SKILL.md - Antigravity:
~/.gemini/antigravity/skills/trailofbits/skills/wycheproof/SKILL.md
π Install with CLI:npx skills add trailofbits/skills