Conversation
Summary of #244 + #245 implementation: New builtins added: - crypto.sha256 - SHA-256 hash (returns 64-char hex) - crypto.hmac-sha256 - HMAC-SHA256 signature for webhooks/JWTs - crypto.constant-time-eq - Timing-safe comparison (prevents timing attacks) - crypto.random-bytes - Cryptographically secure random bytes - crypto.uuid4 - UUID v4 generation Files created/modified: - crates/runtime/src/crypto.rs - Core implementation with 11 unit tests - crates/runtime/src/lib.rs - Module registration - crates/runtime/Cargo.toml - Added sha2, hmac, rand, uuid deps - Cargo.toml - Workspace dependencies - crates/compiler/src/codegen/runtime.rs - FFI declarations - crates/compiler/src/builtins.rs - LSP signatures and docs - crates/compiler/src/ast.rs - Builtin validation - tests/integration/src/test-crypto.seq - 17 integration tests - examples/crypto.seq - Working demo - docs/BATTERIES_INCLUDED.md - Updated status Test counts: - 231 integration tests (17 new crypto tests) - 11 unit tests in crypto.rs Practical use cases now possible: - Webhook signature verification - JWT token generation/validation - Secure session tokens - API authentication (HMAC) - Content addressing (SHA-256)
Code Review: Phase 1 Crypto Implementation (#254)SummaryThis PR adds cryptographic primitives to Seq, implementing 5 new builtin functions for SHA-256, HMAC, secure random generation, UUID creation, and constant-time comparison. The implementation is well-architected and follows the project's established patterns. Overall, this is high-quality work with excellent test coverage and documentation. ✅ Strengths1. Code Quality
2. Security Practices
3. Test Coverage
4. Documentation
🔍 Issues & RecommendationsCRITICAL: Constant-Time Comparison VulnerabilityLocation: The current implementation has a timing leak when strings have different lengths: let mut result = a_bytes.len() ^ b_bytes.len();
for (x, y) in a_bytes.iter().zip(b_bytes.iter()) {
result |= (*x as usize) ^ (*y as usize);
}Problem: When lengths differ, the loop terminates early (zip stops at the shorter length), leaking timing information about the length difference. Fix: Use the use subtle::ConstantTimeEq;
let a_bytes = a.as_str().as_bytes();
let b_bytes = b.as_str().as_bytes();
let eq = a_bytes.ct_eq(b_bytes);
unsafe { push(stack, Value::Bool(bool::from(eq))) }Why this matters: Timing attacks can extract secrets byte-by-byte. The Minor: Random Bytes LimitLocation: The 1024-byte limit is reasonable for preventing abuse, but:
Minor: HMAC Key SizeLocation: HmacSha256::new_from_slice(key.as_str().as_bytes()).expect("HMAC can take any key")While technically true that HMAC accepts any key size, security best practices recommend:
Minor: Missing Input ValidationSHA-256 and HMAC functions don't validate input sizes. While unlikely to cause issues, extremely large strings could:
Recommendation: Consider adding a reasonable limit (e.g., 10MB) with a clear error message, or document that callers should validate input sizes in security-critical contexts. Nitpick: Error MessagesError messages use panic!("sha256: expected String on stack, got {:?}", value)For Strings, this could leak sensitive data in logs. Consider using type-only error messages: panic!("sha256: expected String on stack, got {}", value.type_name())📋 Architecture & IntegrationPositive
Observations
🧪 Test QualityUnit Tests
Integration Tests
Missing Tests
🔐 Security AssessmentStrengths
Weaknesses
Recommendations
📊 Performance
🎯 Best Practices ComplianceRust
Crypto
📝 Documentation ReviewInline Docs
Examples
Missing
✅ Checklist
🚀 RecommendationApprove with requested changes. This is solid work that enables important use cases (JWT, webhooks, secure tokens). The only blocking issue is the constant-time comparison timing leak. Required Before Merge
Recommended Enhancements
Nice to Have
Great work implementing Phase 1 crypto! This brings Seq much closer to real-world application development. The test coverage is excellent and the API design is clean and intuitive. Once the constant-time comparison is fixed, this will be production-ready. |
…ress the PR review:
Fixed: Constant-time comparison timing leak
Changed crypto.rs to use subtle::ConstantTimeEq instead of manual XOR:
// Before (had timing leak when lengths differ):
let mut result = a_bytes.len() ^ b_bytes.len();
for (x, y) in a_bytes.iter().zip(b_bytes.iter()) {
result |= (*x as usize) ^ (*y as usize);
}
// After (truly constant-time):
let eq = a_bytes.ct_eq(b_bytes);
Additional improvements:
- Added subtle = "2.6" to workspace dependencies
- Documented 1024-byte limit in random-bytes docstring
- Added unit test for max limit (1024 bytes)
Files modified:
- Cargo.toml - added subtle dependency
- crates/runtime/Cargo.toml - added subtle dependency
- crates/runtime/src/crypto.rs - fixed constant-time comparison, added docs/test
- Cargo.lock - updated
Code Review: PR #254 - Crypto Phase 1 ImplementationSummaryThis PR adds 5 cryptographic builtins to Seq: sha256, hmac-sha256, constant-time-eq, random-bytes, and uuid4. The implementation is excellent. Code Quality - EXCELLENT
Security - EXCELLENT
Performance - GOOD
Test Coverage - EXCELLENTAll critical paths tested including edge cases: empty strings, zero-length, different lengths, max limits, uniqueness. Verdict: STRONGLY RECOMMEND MERGINGThis is production-ready code that follows security best practices and enables real-world use cases like JWT verification and webhook handling. Minor suggestions (not blockers):
Great work! Phase 1 crypto complete. |
Detailed Technical ReviewCode Quality DetailsStrengths:
Minor improvements:
Security AnalysisConstant-time comparison (Lines 108-130):
HMAC-SHA256 (Lines 72-92):
Random generation (Lines 146-167):
UUID v4 (Lines 178-183):
Test Coverage AnalysisWhat's tested:
What could be added (not critical):
Performance Notes
Documentation Quality
|
Summary of #244 + #245 implementation:
#244
#245
New builtins added:
Files created/modified:
Test counts:
Practical use cases now possible: