Merge branch 'main' of https://github.com/lockbitchat/lockbit-chat
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 lockbitchat
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
95
README.md
Normal file
95
README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# lockbit-chat
|
||||
🔒 World's most secure P2P messenger with Lightning Network integration. End-to-end encryption, pay-per-session model, zero data collection. WebRTC direct connections, quantum-resistant roadmap. Privacy-first communication for the Bitcoin age ⚡
|
||||
|
||||
🛡️ LockBit.chat - Enhanced Security Edition
|
||||
🎯 About the Project
|
||||
LockBit.chat is a revolutionary P2P messenger that combines:
|
||||
|
||||
Military-grade cryptography (ECDH P-384 + AES-GCM 256)
|
||||
Lightning Network payments for sessions
|
||||
Perfect Forward Secrecy with automatic key rotation
|
||||
Zero-trust architecture without servers
|
||||
|
||||
✨ Key Features
|
||||
🔐 Cryptography
|
||||
|
||||
ECDH P-384 key exchange
|
||||
AES-GCM 256-bit encryption
|
||||
ECDSA digital signatures
|
||||
Perfect Forward Secrecy
|
||||
Out-of-band verification against MITM attacks
|
||||
|
||||
⚡ Lightning Network
|
||||
|
||||
Payments in satoshis for sessions
|
||||
WebLN support
|
||||
Instant microtransactions
|
||||
Private payments
|
||||
|
||||
🌐 P2P Architecture
|
||||
|
||||
Direct connection via WebRTC
|
||||
No central servers
|
||||
Impossible to censor
|
||||
No metadata collection
|
||||
|
||||
🚀 Quick Start
|
||||
|
||||
Open: https://lockbit.chat
|
||||
Choose: "Create Channel" or "Join"
|
||||
Pay: for session via Lightning
|
||||
Chat: securely!
|
||||
|
||||
🔒 Security
|
||||
Cryptographic Algorithms:
|
||||
🔑 Key Exchange: ECDH P-384
|
||||
🔐 Encryption: AES-GCM 256-bit
|
||||
✍️ Signatures: ECDSA P-384
|
||||
🔄 PFS: Automatic key rotation
|
||||
🛡️ MITM Protection: Out-of-band verification
|
||||
Security Audit:
|
||||
|
||||
✅ All algorithms verified by cryptographers
|
||||
✅ Code open for independent audit
|
||||
✅ Uses only standard WebCrypto APIs
|
||||
✅ Non-extractable keys
|
||||
|
||||
🗺️ Roadmap
|
||||
|
||||
v4.0 ✅ Enhanced Security Edition (current)
|
||||
v4.5 🔄 Mobile & Desktop applications
|
||||
v5.0 📅 Quantum-resistant cryptography
|
||||
v5.5 📅 Group chats
|
||||
v6.0 📅 Decentralized network
|
||||
|
||||
🛠️ For Developers
|
||||
Technologies:
|
||||
|
||||
Frontend: Vanilla JS + React
|
||||
Crypto: Web Crypto API
|
||||
P2P: WebRTC DataChannels
|
||||
Payments: Lightning Network / WebLN
|
||||
|
||||
Local Development:
|
||||
bashgit clone https://github.com/lockbitchat/lockbit-chat.git
|
||||
cd lockbit-chat
|
||||
python -m http.server 8000
|
||||
# Open http://localhost:8000
|
||||
🤝 Contributing
|
||||
We welcome community contributions!
|
||||
How to help:
|
||||
|
||||
🐛 Report bugs
|
||||
💡 Suggest ideas
|
||||
🔍 Security audit
|
||||
📖 Improve documentation
|
||||
🌍 Translations
|
||||
|
||||
📄 License
|
||||
MIT License with mandatory attribution
|
||||
⚠️ Disclaimer
|
||||
LockBit.chat is provided "as is". Use at your own risk. For mission-critical communications, additional security verification is recommended.
|
||||
📞 Contacts
|
||||
|
||||
🌐 Website: https://lockbit.chat
|
||||
📧 Email: lockbitchat@tutanota.com
|
||||
166
SECURITY.md
Normal file
166
SECURITY.md
Normal file
@@ -0,0 +1,166 @@
|
||||
# Security Policy
|
||||
|
||||
## 🛡️ Security Overview
|
||||
|
||||
LockBit.chat is built with security-first principles. We take security vulnerabilities seriously and appreciate responsible disclosure from the security community.
|
||||
|
||||
## 🔒 Security Features
|
||||
|
||||
### Cryptographic Implementation
|
||||
- **Key Exchange:** ECDH P-384 (NIST recommended curve)
|
||||
- **Encryption:** AES-GCM 256-bit with authenticated encryption
|
||||
- **Digital Signatures:** ECDSA P-384 for message authenticity
|
||||
- **Perfect Forward Secrecy:** Automatic key rotation every 5 minutes
|
||||
- **Non-extractable Keys:** All cryptographic keys are hardware-protected
|
||||
- **MITM Protection:** Out-of-band verification codes
|
||||
|
||||
### Architecture Security
|
||||
- **Zero-trust Model:** No central servers to compromise
|
||||
- **P2P Direct:** WebRTC encrypted channels
|
||||
- **No Data Persistence:** Messages exist only in memory
|
||||
- **Rate Limiting:** Protection against spam and DoS
|
||||
- **Replay Protection:** Sequence numbers and message IDs
|
||||
|
||||
## 🚨 Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 4.0.x | ✅ Yes |
|
||||
| < 4.0 | ❌ No |
|
||||
|
||||
## 📋 Reporting a Vulnerability
|
||||
|
||||
### 🔴 Critical Vulnerabilities
|
||||
For **critical security issues** that could compromise user safety:
|
||||
|
||||
**DO NOT** create a public GitHub issue.
|
||||
|
||||
**Contact us privately:**
|
||||
- 📧 **Email:** security@lockbit.chat (PGP key below)
|
||||
- 🔒 **Signal:** +[REDACTED] (ask for Signal number via email)
|
||||
- 🔐 **Keybase:** @lockbitchat
|
||||
|
||||
### 🟡 Non-Critical Issues
|
||||
For general security improvements or non-critical findings:
|
||||
- Create a GitHub issue with `[SECURITY]` prefix
|
||||
- Use our security issue template
|
||||
|
||||
## 📝 Vulnerability Disclosure Process
|
||||
|
||||
1. **Report:** Send details to security@lockbit.chat
|
||||
2. **Acknowledgment:** We'll respond within 24 hours
|
||||
3. **Investigation:** We'll investigate and keep you updated
|
||||
4. **Fix:** We'll develop and test a fix
|
||||
5. **Disclosure:** Public disclosure after fix is deployed
|
||||
6. **Credit:** We'll credit you in our security hall of fame
|
||||
|
||||
### Timeline Expectations
|
||||
- **Initial Response:** < 24 hours
|
||||
- **Status Update:** Every 72 hours
|
||||
- **Fix Timeline:** Critical bugs < 7 days, Others < 30 days
|
||||
|
||||
## 🏆 Security Hall of Fame
|
||||
|
||||
We maintain a hall of fame for security researchers who help improve LockBit.chat:
|
||||
|
||||
<!-- Security researchers will be listed here -->
|
||||
*Be the first to help secure LockBit.chat!*
|
||||
|
||||
## 🔍 Security Audit History
|
||||
|
||||
### Independent Audits
|
||||
- **Pending:** Professional cryptographic audit (Q2 2025)
|
||||
- **Community:** Ongoing peer review by security researchers
|
||||
|
||||
### Internal Security Measures
|
||||
- **Code Review:** All cryptographic code reviewed by multiple developers
|
||||
- **Testing:** Comprehensive security test suite
|
||||
- **Dependencies:** Regular security updates for all dependencies
|
||||
|
||||
## 🛠️ Security Best Practices for Users
|
||||
|
||||
### For Maximum Security:
|
||||
1. **Verify Authenticity:** Always verify out-of-band codes
|
||||
2. **Use Official Source:** Only use https://lockbit.chat
|
||||
3. **Keep Updated:** Use the latest version
|
||||
4. **Secure Environment:** Use updated browsers on secure devices
|
||||
5. **Lightning Wallets:** Use reputable Lightning wallets (Alby, Zeus, etc.)
|
||||
|
||||
### Red Flags:
|
||||
- ❌ Codes don't match during verification
|
||||
- ❌ Unusual connection behavior
|
||||
- ❌ Requests for private keys or seed phrases
|
||||
- ❌ Unofficial domains or mirrors
|
||||
|
||||
## 🔬 Security Research Guidelines
|
||||
|
||||
### Scope
|
||||
**In Scope:**
|
||||
- ✅ Cryptographic implementation flaws
|
||||
- ✅ WebRTC security issues
|
||||
- ✅ Authentication bypass
|
||||
- ✅ Input validation vulnerabilities
|
||||
- ✅ Client-side security issues
|
||||
|
||||
**Out of Scope:**
|
||||
- ❌ Social engineering attacks
|
||||
- ❌ Physical attacks on user devices
|
||||
- ❌ DoS attacks on user connections
|
||||
- ❌ Issues requiring physical access
|
||||
- ❌ Lightning Network protocol issues
|
||||
|
||||
### Research Ethics
|
||||
- **No Disruption:** Don't interfere with live users
|
||||
- **Responsible Disclosure:** Follow our disclosure timeline
|
||||
- **No Data Harvesting:** Don't collect user communications
|
||||
- **Legal Compliance:** Follow all applicable laws
|
||||
|
||||
## 📊 Security Metrics
|
||||
|
||||
We track and publish these security metrics:
|
||||
- **Response Time:** Average time to acknowledge reports
|
||||
- **Fix Time:** Average time to deploy fixes
|
||||
- **Vulnerability Count:** Number of reported/fixed issues
|
||||
- **Audit Coverage:** Percentage of code under security review
|
||||
|
||||
## 🔄 Security Updates
|
||||
|
||||
### How We Notify Users:
|
||||
- **Critical:** Immediate notification on website
|
||||
- **Important:** GitHub releases and social media
|
||||
- **Minor:** Regular update cycles
|
||||
|
||||
### Auto-Update Policy:
|
||||
- **Critical Security Fixes:** Automatic for web version
|
||||
- **Feature Updates:** User-controlled
|
||||
- **Breaking Changes:** Advance notice with migration guide
|
||||
|
||||
## 🤝 Working with Security Researchers
|
||||
|
||||
We value the security community and offer:
|
||||
- **Recognition:** Public credit and hall of fame listing
|
||||
- **Swag:** LockBit.chat merchandise for quality reports
|
||||
- **References:** LinkedIn recommendations for exceptional work
|
||||
- **Early Access:** Beta access to new security features
|
||||
|
||||
## 📚 Security Resources
|
||||
|
||||
### Technical Documentation:
|
||||
- [Cryptographic Architecture](docs/CRYPTOGRAPHY.md)
|
||||
- [P2P Security Model](docs/P2P-SECURITY.md)
|
||||
- [Lightning Integration Security](docs/LIGHTNING-SECURITY.md)
|
||||
|
||||
### External Resources:
|
||||
- [WebRTC Security Guide](https://webrtc-security.github.io/)
|
||||
- [Web Crypto API Best Practices](https://www.w3.org/TR/WebCryptoAPI/)
|
||||
- [Lightning Network Security](https://lightning.network/lightning-network-paper.pdf)
|
||||
|
||||
## 📞 Contact Information
|
||||
|
||||
- **Security Team:** security@lockbit.chat
|
||||
- **General Contact:** lockbitchat@tutanota.com
|
||||
- **GitHub Issues:** https://github.com/lockbitchat/lockbit-chat/issues
|
||||
|
||||
---
|
||||
|
||||
*This security policy is reviewed and updated quarterly. Last updated: 08/09/2025*
|
||||
859
doc/API.md
Normal file
859
doc/API.md
Normal file
@@ -0,0 +1,859 @@
|
||||
# LockBit.chat API Documentation
|
||||
|
||||
## 🏗️ Architecture Overview
|
||||
|
||||
LockBit.chat is built as a client-side application with no backend servers. The "API" consists of JavaScript classes and methods that handle cryptography, P2P connections, and Lightning Network integration.
|
||||
|
||||
## 📚 Core Classes
|
||||
|
||||
### 🔐 EnhancedSecureCryptoUtils
|
||||
|
||||
Central cryptographic utilities class providing military-grade encryption.
|
||||
|
||||
#### Key Generation
|
||||
|
||||
##### `generateECDHKeyPair()`
|
||||
``javascript
|
||||
static async generateECDHKeyPair(): Promise<CryptoKeyPair>
|
||||
Generates non-extractable ECDH P-384 key pair for secure key exchange.
|
||||
Returns: CryptoKeyPair with P-384 keys
|
||||
Throws: Error if key generation fails
|
||||
Example:
|
||||
javascriptconst keyPair = await EnhancedSecureCryptoUtils.generateECDHKeyPair();
|
||||
console.log(keyPair.privateKey.algorithm.namedCurve); // "P-384"
|
||||
generateECDSAKeyPair()
|
||||
javascriptstatic async generateECDSAKeyPair(): Promise<CryptoKeyPair>
|
||||
Generates non-extractable ECDSA P-384 key pair for digital signatures.
|
||||
Returns: CryptoKeyPair for signing and verification
|
||||
Throws: Error if key generation fails
|
||||
Encryption/Decryption
|
||||
encryptMessage()
|
||||
javascriptstatic async encryptMessage(
|
||||
message: string,
|
||||
encryptionKey: CryptoKey,
|
||||
macKey: CryptoKey,
|
||||
metadataKey: CryptoKey,
|
||||
messageId: string,
|
||||
sequenceNumber: number = 0
|
||||
): Promise<EncryptedMessage>
|
||||
Encrypts a message with metadata protection and sequence numbers.
|
||||
Parameters:
|
||||
|
||||
message - Plaintext message (max 2000 chars)
|
||||
encryptionKey - AES-GCM 256-bit key
|
||||
macKey - HMAC key for authentication
|
||||
metadataKey - Key for metadata encryption
|
||||
messageId - Unique message identifier
|
||||
sequenceNumber - Message sequence for replay protection
|
||||
|
||||
Returns:
|
||||
typescriptinterface EncryptedMessage {
|
||||
messageIv: number[];
|
||||
messageData: number[];
|
||||
metadataIv: number[];
|
||||
metadataData: number[];
|
||||
mac: number[];
|
||||
version: string;
|
||||
}
|
||||
Example:
|
||||
javascriptconst encrypted = await EnhancedSecureCryptoUtils.encryptMessage(
|
||||
"Hello, secure world!",
|
||||
encryptionKey,
|
||||
macKey,
|
||||
metadataKey,
|
||||
"msg_12345",
|
||||
42
|
||||
);
|
||||
decryptMessage()
|
||||
javascriptstatic async decryptMessage(
|
||||
encryptedPayload: EncryptedMessage,
|
||||
encryptionKey: CryptoKey,
|
||||
macKey: CryptoKey,
|
||||
metadataKey: CryptoKey,
|
||||
expectedSequenceNumber?: number
|
||||
): Promise<DecryptedMessage>
|
||||
Decrypts and verifies an encrypted message.
|
||||
Returns:
|
||||
typescriptinterface DecryptedMessage {
|
||||
message: string;
|
||||
messageId: string;
|
||||
timestamp: number;
|
||||
sequenceNumber: number;
|
||||
}
|
||||
Key Exchange
|
||||
deriveSharedKeys()
|
||||
javascriptstatic async deriveSharedKeys(
|
||||
privateKey: CryptoKey,
|
||||
publicKey: CryptoKey,
|
||||
salt: Uint8Array
|
||||
): Promise<SharedKeys>
|
||||
Derives shared encryption keys using ECDH + HKDF.
|
||||
Parameters:
|
||||
|
||||
privateKey - Local ECDH private key
|
||||
publicKey - Remote ECDH public key
|
||||
salt - 64-byte cryptographic salt
|
||||
|
||||
Returns:
|
||||
typescriptinterface SharedKeys {
|
||||
encryptionKey: CryptoKey;
|
||||
macKey: CryptoKey;
|
||||
metadataKey: CryptoKey;
|
||||
fingerprint: string;
|
||||
timestamp: number;
|
||||
version: string;
|
||||
}
|
||||
Example:
|
||||
javascriptconst salt = EnhancedSecureCryptoUtils.generateSalt();
|
||||
const sharedKeys = await EnhancedSecureCryptoUtils.deriveSharedKeys(
|
||||
localPrivateKey,
|
||||
remotePublicKey,
|
||||
salt
|
||||
);
|
||||
console.log('Key fingerprint:', sharedKeys.fingerprint);
|
||||
Digital Signatures
|
||||
signData()
|
||||
javascriptstatic async signData(
|
||||
privateKey: CryptoKey,
|
||||
data: string | Uint8Array
|
||||
): Promise<number[]>
|
||||
Signs data with ECDSA P-384.
|
||||
Parameters:
|
||||
|
||||
privateKey - ECDSA private key
|
||||
data - Data to sign
|
||||
|
||||
Returns: Signature as byte array
|
||||
Example:
|
||||
javascriptconst signature = await EnhancedSecureCryptoUtils.signData(
|
||||
ecdsaPrivateKey,
|
||||
"Important message"
|
||||
);
|
||||
verifySignature()
|
||||
javascriptstatic async verifySignature(
|
||||
publicKey: CryptoKey,
|
||||
signature: number[],
|
||||
data: string | Uint8Array
|
||||
): Promise<boolean>
|
||||
Verifies ECDSA signature.
|
||||
Returns: true if signature is valid
|
||||
Authentication
|
||||
generateMutualAuthChallenge()
|
||||
javascriptstatic generateMutualAuthChallenge(): AuthChallenge
|
||||
Generates cryptographic challenge for mutual authentication.
|
||||
Returns:
|
||||
typescriptinterface AuthChallenge {
|
||||
challenge: number[];
|
||||
timestamp: number;
|
||||
nonce: number[];
|
||||
version: string;
|
||||
}
|
||||
createAuthProof()
|
||||
javascriptstatic async createAuthProof(
|
||||
challenge: AuthChallenge,
|
||||
privateKey: CryptoKey,
|
||||
publicKey: CryptoKey
|
||||
): Promise<AuthProof>
|
||||
Creates cryptographic proof for challenge response.
|
||||
Returns:
|
||||
typescriptinterface AuthProof {
|
||||
challenge: number[];
|
||||
timestamp: number;
|
||||
nonce: number[];
|
||||
responseTimestamp: number;
|
||||
publicKeyHash: string;
|
||||
signature: number[];
|
||||
version: string;
|
||||
}
|
||||
verifyAuthProof()
|
||||
javascriptstatic async verifyAuthProof(
|
||||
proof: AuthProof,
|
||||
challenge: AuthChallenge,
|
||||
publicKey: CryptoKey
|
||||
): Promise<boolean>
|
||||
Verifies authentication proof against challenge.
|
||||
Utility Functions
|
||||
generateSalt()
|
||||
javascriptstatic generateSalt(): number[]
|
||||
Generates 64-byte cryptographically secure salt.
|
||||
sanitizeMessage()
|
||||
javascriptstatic sanitizeMessage(message: string): string
|
||||
Sanitizes user input to prevent XSS attacks.
|
||||
Example:
|
||||
javascriptconst clean = EnhancedSecureCryptoUtils.sanitizeMessage("<script>alert('xss')</script>Hello");
|
||||
// Returns: "Hello"
|
||||
calculateSecurityLevel()
|
||||
javascriptstatic async calculateSecurityLevel(securityManager: any): Promise<SecurityLevel>
|
||||
Calculates real-time security level based on active protections.
|
||||
Returns:
|
||||
typescriptinterface SecurityLevel {
|
||||
level: 'HIGH' | 'MEDIUM' | 'LOW' | 'UNKNOWN';
|
||||
score: number; // 0-100
|
||||
color: 'green' | 'yellow' | 'red';
|
||||
verificationResults: Record<string, VerificationResult>;
|
||||
timestamp: number;
|
||||
details: string;
|
||||
}
|
||||
|
||||
interface VerificationResult {
|
||||
passed: boolean;
|
||||
details: string;
|
||||
}
|
||||
generateVerificationCode()
|
||||
javascriptstatic generateVerificationCode(): string
|
||||
Generates 6-character verification code for out-of-band authentication.
|
||||
Returns: Code in format "AB-CD-EF"
|
||||
calculateKeyFingerprint()
|
||||
javascriptstatic async calculateKeyFingerprint(keyData: number[]): Promise<string>
|
||||
Calculates SHA-256 fingerprint of key data for MITM protection.
|
||||
encryptData() / decryptData()
|
||||
javascriptstatic async encryptData(data: any, password: string): Promise<string>
|
||||
static async decryptData(encryptedData: string, password: string): Promise<any>
|
||||
High-level encryption/decryption for offer/answer exchange.
|
||||
Example:
|
||||
javascriptconst password = EnhancedSecureCryptoUtils.generateSecurePassword();
|
||||
const encrypted = await EnhancedSecureCryptoUtils.encryptData(
|
||||
{ message: "secret data" },
|
||||
password
|
||||
);
|
||||
const decrypted = await EnhancedSecureCryptoUtils.decryptData(encrypted, password);
|
||||
🌐 EnhancedSecureWebRTCManager
|
||||
Manages P2P connections with enhanced security features.
|
||||
Constructor
|
||||
javascriptnew EnhancedSecureWebRTCManager(
|
||||
onMessage: (message: string, type: string) => void,
|
||||
onStatusChange: (status: string) => void,
|
||||
onKeyExchange: (fingerprint: string) => void,
|
||||
onVerificationRequired: (code: string) => void
|
||||
)
|
||||
Parameters:
|
||||
|
||||
onMessage - Callback for received messages
|
||||
onStatusChange - Callback for connection state changes
|
||||
onKeyExchange - Callback when keys are exchanged
|
||||
onVerificationRequired - Callback when verification code is generated
|
||||
|
||||
Connection Management
|
||||
createSecureOffer()
|
||||
javascriptasync createSecureOffer(): Promise<SecureOffer>
|
||||
Creates encrypted connection offer with ECDH keys and authentication.
|
||||
Returns:
|
||||
typescriptinterface SecureOffer {
|
||||
type: 'enhanced_secure_offer';
|
||||
sdp: string;
|
||||
ecdhPublicKey: SignedPublicKey;
|
||||
ecdsaPublicKey: SignedPublicKey;
|
||||
salt: number[];
|
||||
verificationCode: string;
|
||||
authChallenge: AuthChallenge;
|
||||
sessionId: string;
|
||||
timestamp: number;
|
||||
version: string;
|
||||
securityLevel: SecurityLevel;
|
||||
}
|
||||
|
||||
interface SignedPublicKey {
|
||||
keyType: 'ECDH' | 'ECDSA';
|
||||
keyData: number[];
|
||||
timestamp: number;
|
||||
version: string;
|
||||
signature: number[];
|
||||
}
|
||||
Example:
|
||||
javascriptconst webrtcManager = new EnhancedSecureWebRTCManager(/*...*/);
|
||||
const offer = await webrtcManager.createSecureOffer();
|
||||
console.log('Verification code:', offer.verificationCode);
|
||||
createSecureAnswer()
|
||||
javascriptasync createSecureAnswer(offerData: SecureOffer): Promise<SecureAnswer>
|
||||
Creates encrypted response to connection offer.
|
||||
Returns:
|
||||
typescriptinterface SecureAnswer {
|
||||
type: 'enhanced_secure_answer';
|
||||
sdp: string;
|
||||
ecdhPublicKey: SignedPublicKey;
|
||||
ecdsaPublicKey: SignedPublicKey;
|
||||
authProof: AuthProof;
|
||||
timestamp: number;
|
||||
version: string;
|
||||
securityLevel: SecurityLevel;
|
||||
}
|
||||
handleSecureAnswer()
|
||||
javascriptasync handleSecureAnswer(answerData: SecureAnswer): Promise<void>
|
||||
Processes encrypted answer and establishes connection.
|
||||
Throws: Error if answer is invalid or authentication fails
|
||||
Message Handling
|
||||
sendSecureMessage()
|
||||
javascriptasync sendSecureMessage(message: string): Promise<void>
|
||||
Sends encrypted message through secure channel.
|
||||
Parameters:
|
||||
|
||||
message - Plaintext message (auto-sanitized)
|
||||
|
||||
Features:
|
||||
|
||||
Automatic encryption with metadata protection
|
||||
Sequence number tracking
|
||||
Rate limiting (60 messages/minute)
|
||||
Perfect Forward Secrecy key rotation
|
||||
|
||||
Example:
|
||||
javascriptawait webrtcManager.sendSecureMessage("Hello, secure world!");
|
||||
Connection States
|
||||
typescripttype ConnectionState =
|
||||
| 'disconnected' // No connection
|
||||
| 'connecting' // Establishing connection
|
||||
| 'verifying' // Verifying security codes
|
||||
| 'connected' // Fully connected and verified
|
||||
| 'failed' // Connection failed
|
||||
| 'reconnecting' // Attempting to reconnect
|
||||
| 'peer_disconnected'; // Peer disconnected
|
||||
Security Features
|
||||
calculateSecurityLevel()
|
||||
javascriptasync calculateSecurityLevel(): Promise<SecurityLevel>
|
||||
Real-time security assessment with verification of:
|
||||
|
||||
✅ Encryption functionality
|
||||
✅ ECDH key exchange
|
||||
✅ ECDSA signatures
|
||||
✅ Mutual authentication
|
||||
✅ Metadata protection
|
||||
✅ Replay protection
|
||||
✅ Non-extractable keys
|
||||
✅ Rate limiting
|
||||
✅ Perfect Forward Secrecy
|
||||
|
||||
shouldRotateKeys()
|
||||
javascriptshouldRotateKeys(): boolean
|
||||
Determines if PFS key rotation is needed (every 5 minutes or 100 messages).
|
||||
isConnected()
|
||||
javascriptisConnected(): boolean
|
||||
Returns true if WebRTC data channel is open and ready.
|
||||
getConnectionInfo()
|
||||
javascriptgetConnectionInfo(): ConnectionInfo
|
||||
Returns:
|
||||
typescriptinterface ConnectionInfo {
|
||||
fingerprint: string;
|
||||
isConnected: boolean;
|
||||
isVerified: boolean;
|
||||
connectionState: string;
|
||||
iceConnectionState: string;
|
||||
verificationCode: string;
|
||||
}
|
||||
Perfect Forward Secrecy
|
||||
rotateKeys()
|
||||
javascriptasync rotateKeys(): Promise<boolean>
|
||||
Performs key rotation for Perfect Forward Secrecy.
|
||||
Returns: true if rotation successful
|
||||
getKeysForVersion()
|
||||
javascriptgetKeysForVersion(version: number): KeySet | null
|
||||
Retrieves keys for specific version (for decrypting old messages).
|
||||
Returns:
|
||||
typescriptinterface KeySet {
|
||||
encryptionKey: CryptoKey;
|
||||
macKey: CryptoKey;
|
||||
metadataKey: CryptoKey;
|
||||
}
|
||||
Connection Control
|
||||
disconnect()
|
||||
javascriptdisconnect(): void
|
||||
Cleanly disconnects and cleans up all resources.
|
||||
confirmVerification()
|
||||
javascriptconfirmVerification(): void
|
||||
Confirms that verification codes match (called after manual verification).
|
||||
⚡ PayPerSessionManager
|
||||
Handles Lightning Network payment integration.
|
||||
Constructor
|
||||
javascriptnew PayPerSessionManager()
|
||||
Session Types
|
||||
typescriptinterface SessionPricing {
|
||||
free: { sats: 0, hours: 1/60, usd: 0.00 };
|
||||
basic: { sats: 500, hours: 1, usd: 0.20 };
|
||||
premium: { sats: 1000, hours: 4, usd: 0.40 };
|
||||
extended: { sats: 2000, hours: 24, usd: 0.80 };
|
||||
}
|
||||
Payment Methods
|
||||
createInvoice()
|
||||
javascriptcreateInvoice(sessionType: string): LightningInvoice
|
||||
Creates Lightning invoice for session payment.
|
||||
Parameters:
|
||||
|
||||
sessionType - One of: 'free', 'basic', 'premium', 'extended'
|
||||
|
||||
Returns:
|
||||
typescriptinterface LightningInvoice {
|
||||
amount: number; // satoshis
|
||||
memo: string;
|
||||
sessionType: string;
|
||||
timestamp: number;
|
||||
paymentHash: string;
|
||||
lightningAddress: string;
|
||||
}
|
||||
Example:
|
||||
javascriptconst sessionManager = new PayPerSessionManager();
|
||||
const invoice = sessionManager.createInvoice('premium');
|
||||
console.log(`Pay ${invoice.amount} sats to ${invoice.lightningAddress}`);
|
||||
verifyPayment()
|
||||
javascriptasync verifyPayment(preimage: string, paymentHash: string): Promise<boolean>
|
||||
Verifies Lightning payment preimage.
|
||||
Parameters:
|
||||
|
||||
preimage - Payment preimage (64 hex characters)
|
||||
paymentHash - Payment hash from invoice
|
||||
|
||||
Returns: true if payment is valid
|
||||
activateSession()
|
||||
javascriptactivateSession(sessionType: string, preimage: string): Session
|
||||
Activates paid session.
|
||||
Returns:
|
||||
typescriptinterface Session {
|
||||
type: string;
|
||||
startTime: number;
|
||||
expiresAt: number;
|
||||
preimage: string;
|
||||
}
|
||||
Session Management
|
||||
hasActiveSession()
|
||||
javascripthasActiveSession(): boolean
|
||||
Returns true if there's an active, non-expired session.
|
||||
getTimeLeft()
|
||||
javascriptgetTimeLeft(): number
|
||||
Returns milliseconds remaining in current session.
|
||||
Example:
|
||||
javascriptconst timeLeft = sessionManager.getTimeLeft();
|
||||
const hoursLeft = Math.floor(timeLeft / (1000 * 60 * 60));
|
||||
console.log(`${hoursLeft} hours remaining`);
|
||||
cleanup()
|
||||
javascriptcleanup(): void
|
||||
Cleans up session data and timers.
|
||||
🔧 Integration Examples
|
||||
Basic P2P Chat Setup
|
||||
javascript// Initialize WebRTC manager
|
||||
const webrtcManager = new EnhancedSecureWebRTCManager(
|
||||
(message, type) => {
|
||||
console.log(`${type}: ${message}`);
|
||||
addMessageToUI(message, type);
|
||||
},
|
||||
(status) => {
|
||||
console.log(`Status: ${status}`);
|
||||
updateStatusIndicator(status);
|
||||
},
|
||||
(fingerprint) => {
|
||||
console.log(`Key fingerprint: ${fingerprint}`);
|
||||
displayFingerprint(fingerprint);
|
||||
},
|
||||
(code) => {
|
||||
console.log(`Verification code: ${code}`);
|
||||
showVerificationModal(code);
|
||||
}
|
||||
);
|
||||
|
||||
// Create secure offer
|
||||
const offer = await webrtcManager.createSecureOffer();
|
||||
console.log('Share this encrypted offer:', JSON.stringify(offer));
|
||||
|
||||
// Send message (after connection established)
|
||||
await webrtcManager.sendSecureMessage('Hello, secure world!');
|
||||
Lightning Payment Integration
|
||||
javascript// Initialize session manager
|
||||
const sessionManager = new PayPerSessionManager();
|
||||
|
||||
// Create invoice for premium session
|
||||
const invoice = sessionManager.createInvoice('premium');
|
||||
console.log(`Pay ${invoice.amount} sats to: ${invoice.lightningAddress}`);
|
||||
|
||||
// Handle payment (WebLN)
|
||||
if (window.webln) {
|
||||
try {
|
||||
await window.webln.enable();
|
||||
const result = await window.webln.sendPayment({
|
||||
amount: invoice.amount,
|
||||
memo: invoice.memo
|
||||
});
|
||||
|
||||
// Verify and activate session
|
||||
const isValid = await sessionManager.verifyPayment(
|
||||
result.preimage,
|
||||
invoice.paymentHash
|
||||
);
|
||||
|
||||
if (isValid) {
|
||||
const session = sessionManager.activateSession('premium', result.preimage);
|
||||
console.log(`Session active until: ${new Date(session.expiresAt)}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('WebLN payment failed:', error);
|
||||
}
|
||||
}
|
||||
Custom Cryptographic Operations
|
||||
javascript// Generate fresh key pairs
|
||||
const ecdhKeys = await EnhancedSecureCryptoUtils.generateECDHKeyPair();
|
||||
const ecdsaKeys = await EnhancedSecureCryptoUtils.generateECDSAKeyPair();
|
||||
|
||||
// Create and verify signature
|
||||
const data = 'Important message to sign';
|
||||
const signature = await EnhancedSecureCryptoUtils.signData(
|
||||
ecdsaKeys.privateKey,
|
||||
data
|
||||
);
|
||||
|
||||
const isValid = await EnhancedSecureCryptoUtils.verifySignature(
|
||||
ecdsaKeys.publicKey,
|
||||
signature,
|
||||
data
|
||||
);
|
||||
console.log('Signature valid:', isValid);
|
||||
|
||||
// Derive shared keys
|
||||
const salt = EnhancedSecureCryptoUtils.generateSalt();
|
||||
const sharedKeys = await EnhancedSecureCryptoUtils.deriveSharedKeys(
|
||||
ecdhKeys.privateKey,
|
||||
remotePublicKey,
|
||||
salt
|
||||
);
|
||||
|
||||
// Encrypt message
|
||||
const encrypted = await EnhancedSecureCryptoUtils.encryptMessage(
|
||||
"Secret message",
|
||||
sharedKeys.encryptionKey,
|
||||
sharedKeys.macKey,
|
||||
sharedKeys.metadataKey,
|
||||
"msg_001",
|
||||
1
|
||||
);
|
||||
Full Connection Flow
|
||||
javascript// Complete initiator flow
|
||||
async function initiatorFlow() {
|
||||
// 1. Create WebRTC manager
|
||||
const manager = new EnhancedSecureWebRTCManager(
|
||||
handleMessage,
|
||||
handleStatusChange,
|
||||
handleKeyExchange,
|
||||
handleVerification
|
||||
);
|
||||
|
||||
// 2. Create offer
|
||||
const offer = await manager.createSecureOffer();
|
||||
|
||||
// 3. Encrypt offer for sharing
|
||||
const password = EnhancedSecureCryptoUtils.generateSecurePassword();
|
||||
const encryptedOffer = await EnhancedSecureCryptoUtils.encryptData(offer, password);
|
||||
|
||||
// 4. Share encrypted offer and password with peer
|
||||
console.log('Encrypted offer:', encryptedOffer);
|
||||
console.log('Password:', password);
|
||||
|
||||
// 5. Wait for encrypted answer from peer
|
||||
const encryptedAnswer = await getAnswerFromPeer();
|
||||
const answerPassword = await getPasswordFromPeer();
|
||||
|
||||
// 6. Decrypt and process answer
|
||||
const answer = await EnhancedSecureCryptoUtils.decryptData(
|
||||
encryptedAnswer,
|
||||
answerPassword
|
||||
);
|
||||
await manager.handleSecureAnswer(answer);
|
||||
|
||||
// 7. Verify out-of-band codes
|
||||
await verifySecurityCodes();
|
||||
|
||||
// 8. Start secure communication
|
||||
await manager.sendSecureMessage("Hello from initiator!");
|
||||
}
|
||||
Responder Flow
|
||||
javascriptasync function responderFlow() {
|
||||
// 1. Get encrypted offer from initiator
|
||||
const encryptedOffer = await getOfferFromPeer();
|
||||
const offerPassword = await getPasswordFromPeer();
|
||||
|
||||
// 2. Decrypt offer
|
||||
const offer = await EnhancedSecureCryptoUtils.decryptData(
|
||||
encryptedOffer,
|
||||
offerPassword
|
||||
);
|
||||
|
||||
// 3. Create WebRTC manager
|
||||
const manager = new EnhancedSecureWebRTCManager(
|
||||
handleMessage,
|
||||
handleStatusChange,
|
||||
handleKeyExchange,
|
||||
handleVerification
|
||||
);
|
||||
|
||||
// 4. Create answer
|
||||
const answer = await manager.createSecureAnswer(offer);
|
||||
|
||||
// 5. Encrypt answer for sharing
|
||||
const password = EnhancedSecureCryptoUtils.generateSecurePassword();
|
||||
const encryptedAnswer = await EnhancedSecureCryptoUtils.encryptData(answer, password);
|
||||
|
||||
// 6. Share encrypted answer and password
|
||||
await sendAnswerToPeer(encryptedAnswer);
|
||||
await sendPasswordToPeer(password);
|
||||
|
||||
// 7. Verify out-of-band codes
|
||||
await verifySecurityCodes();
|
||||
|
||||
// 8. Start secure communication
|
||||
await manager.sendSecureMessage("Hello from responder!");
|
||||
}
|
||||
🔒 Security Considerations
|
||||
Key Security
|
||||
|
||||
All keys are non-extractable - Cannot be exported from WebCrypto
|
||||
Hardware security module - Keys protected by browser's HSM
|
||||
Perfect Forward Secrecy - Old messages stay secure even if current keys compromised
|
||||
Automatic key rotation - Keys change every 5 minutes
|
||||
|
||||
Message Security
|
||||
|
||||
Authenticated encryption - AES-GCM provides confidentiality + integrity
|
||||
Metadata protection - Message metadata separately encrypted
|
||||
Replay protection - Sequence numbers prevent message replay
|
||||
Rate limiting - Prevents spam and DoS attacks
|
||||
|
||||
Connection Security
|
||||
|
||||
Out-of-band verification - Manual code verification prevents MITM
|
||||
Mutual authentication - Both parties prove identity
|
||||
Direct P2P - No intermediate servers to compromise
|
||||
WebRTC encryption - DTLS transport layer security
|
||||
|
||||
Payment Security
|
||||
|
||||
Lightning Network - No credit card or banking data exposure
|
||||
Preimage verification - Cryptographic proof of payment
|
||||
No payment data stored - Payments verified and discarded
|
||||
|
||||
🐛 Error Handling
|
||||
Common Error Types
|
||||
typescript// Cryptographic errors
|
||||
class CryptoError extends Error {
|
||||
constructor(message: string) {
|
||||
super(`Crypto Error: ${message}`);
|
||||
this.name = 'CryptoError';
|
||||
}
|
||||
}
|
||||
|
||||
// Connection errors
|
||||
class ConnectionError extends Error {
|
||||
constructor(message: string) {
|
||||
super(`Connection Error: ${message}`);
|
||||
this.name = 'ConnectionError';
|
||||
}
|
||||
}
|
||||
|
||||
// Payment errors
|
||||
class PaymentError extends Error {
|
||||
constructor(message: string) {
|
||||
super(`Payment Error: ${message}`);
|
||||
this.name = 'PaymentError';
|
||||
}
|
||||
}
|
||||
Error Recovery Patterns
|
||||
javascript// Robust message sending with retry
|
||||
async function sendMessageWithRetry(manager, message, maxRetries = 3) {
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
await manager.sendSecureMessage(message);
|
||||
return; // Success
|
||||
} catch (error) {
|
||||
console.warn(`Send attempt ${attempt} failed:`, error.message);
|
||||
|
||||
if (error.message.includes('Session expired')) {
|
||||
throw new PaymentError('Session expired - payment required');
|
||||
}
|
||||
|
||||
if (error.message.includes('Rate limit')) {
|
||||
// Wait before retry
|
||||
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attempt === maxRetries) {
|
||||
throw error; // Final attempt failed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connection error handling
|
||||
function handleConnectionError(error) {
|
||||
if (error.message.includes('MITM')) {
|
||||
alert('⚠️ Security threat detected! Connection terminated.');
|
||||
return 'security_threat';
|
||||
}
|
||||
|
||||
if (error.message.includes('timeout')) {
|
||||
return 'timeout';
|
||||
}
|
||||
|
||||
if (error.message.includes('ice')) {
|
||||
return 'nat_traversal';
|
||||
}
|
||||
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
// Payment error handling
|
||||
function handlePaymentError(error) {
|
||||
if (error.message.includes('preimage')) {
|
||||
return 'invalid_payment';
|
||||
}
|
||||
|
||||
if (error.message.includes('expired')) {
|
||||
return 'session_expired';
|
||||
}
|
||||
|
||||
if (error.message.includes('webln')) {
|
||||
return 'webln_failed';
|
||||
}
|
||||
|
||||
return 'payment_failed';
|
||||
}
|
||||
🧪 Testing
|
||||
Unit Testing Examples
|
||||
javascript// Test encryption/decryption round-trip
|
||||
async function testEncryptionRoundTrip() {
|
||||
const originalMessage = 'Test message for encryption';
|
||||
const keys = await generateTestKeys();
|
||||
|
||||
const encrypted = await EnhancedSecureCryptoUtils.encryptMessage(
|
||||
originalMessage,
|
||||
keys.encryptionKey,
|
||||
keys.macKey,
|
||||
keys.metadataKey,
|
||||
'test-id',
|
||||
0
|
||||
);
|
||||
|
||||
const decrypted = await EnhancedSecureCryptoUtils.decryptMessage(
|
||||
encrypted,
|
||||
keys.encryptionKey,
|
||||
keys.macKey,
|
||||
keys.metadataKey
|
||||
);
|
||||
|
||||
assert.equal(decrypted.message, originalMessage);
|
||||
assert.equal(decrypted.messageId, 'test-id');
|
||||
assert.equal(decrypted.sequenceNumber, 0);
|
||||
}
|
||||
|
||||
// Test key generation
|
||||
async function testKeyGeneration() {
|
||||
const ecdhPair = await EnhancedSecureCryptoUtils.generateECDHKeyPair();
|
||||
const ecdsaPair = await EnhancedSecureCryptoUtils.generateECDSAKeyPair();
|
||||
|
||||
// Verify key properties
|
||||
assert.equal(ecdhPair.privateKey.algorithm.name, 'ECDH');
|
||||
assert.equal(ecdhPair.privateKey.algorithm.namedCurve, 'P-384');
|
||||
assert.equal(ecdhPair.privateKey.extractable, false);
|
||||
|
||||
assert.equal(ecdsaPair.privateKey.algorithm.name, 'ECDSA');
|
||||
assert.equal(ecdsaPair.privateKey.algorithm.namedCurve, 'P-384');
|
||||
assert.equal(ecdsaPair.privateKey.extractable, false);
|
||||
}
|
||||
|
||||
// Test signature verification
|
||||
async function testSignatureVerification() {
|
||||
const keyPair = await EnhancedSecureCryptoUtils.generateECDSAKeyPair();
|
||||
const data = 'Test data to sign';
|
||||
|
||||
const signature = await EnhancedSecureCryptoUtils.signData(
|
||||
keyPair.privateKey,
|
||||
data
|
||||
);
|
||||
|
||||
const isValid = await EnhancedSecureCryptoUtils.verifySignature(
|
||||
keyPair.publicKey,
|
||||
signature,
|
||||
data
|
||||
);
|
||||
|
||||
assert.equal(isValid, true);
|
||||
|
||||
// Test with wrong data
|
||||
const invalidVerification = await EnhancedSecureCryptoUtils.verifySignature(
|
||||
keyPair.publicKey,
|
||||
signature,
|
||||
'Wrong data'
|
||||
);
|
||||
|
||||
assert.equal(invalidVerification, false);
|
||||
}
|
||||
|
||||
// Helper function for tests
|
||||
async function generateTestKeys() {
|
||||
const ecdhPair = await EnhancedSecureCryptoUtils.generateECDHKeyPair();
|
||||
const salt = EnhancedSecureCryptoUtils.generateSalt();
|
||||
|
||||
// For testing, we'll create a mock "remote" key pair
|
||||
const remotePair = await EnhancedSecureCryptoUtils.generateECDHKeyPair();
|
||||
|
||||
const sharedKeys = await EnhancedSecureCryptoUtils.deriveSharedKeys(
|
||||
ecdhPair.privateKey,
|
||||
remotePair.publicKey,
|
||||
salt
|
||||
);
|
||||
|
||||
return sharedKeys;
|
||||
}
|
||||
Integration Testing
|
||||
javascript// Test full P2P connection flow
|
||||
async function testP2PConnection() {
|
||||
let manager1Messages = [];
|
||||
let manager2Messages = [];
|
||||
|
||||
const manager1 = new EnhancedSecureWebRTCManager(
|
||||
(msg, type) => manager1Messages.push({msg, type}),
|
||||
(status) => console.log('Manager1 status:', status),
|
||||
(fingerprint) => console.log('Manager1 fingerprint:', fingerprint),
|
||||
(code) => console.log('Manager1 verification:', code)
|
||||
);
|
||||
|
||||
const manager2 = new EnhancedSecureWebRTCManager(
|
||||
(msg, type) => manager2Messages.push({msg, type}),
|
||||
(status) => console.log('Manager2 status:', status),
|
||||
(fingerprint) => console.log('Manager2 fingerprint:', fingerprint),
|
||||
(code) => console.log('Manager2 verification:', code)
|
||||
);
|
||||
|
||||
// Create offer
|
||||
const offer = await manager1.createSecureOffer();
|
||||
|
||||
// Create answer
|
||||
const answer = await manager2.createSecureAnswer(offer);
|
||||
|
||||
// Handle answer
|
||||
await manager1.handleSecureAnswer(answer);
|
||||
|
||||
// Wait for connection
|
||||
await waitForConnection(manager1, manager2);
|
||||
|
||||
// Verify both are connected
|
||||
assert.equal(manager1.isConnected(), true);
|
||||
assert.equal(manager2.isConnected(), true);
|
||||
|
||||
// Test message exchange
|
||||
await manager1.sendSecureMessage('Hello from manager1');
|
||||
await manager2.sendSecureMessage('Hello from manager2');
|
||||
|
||||
// Wait for messages to arrive
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// Verify messages were received
|
||||
assert.equal(manager2Messages.length > 0, true);
|
||||
assert.equal(manager1Messages.length > 0, true);
|
||||
}
|
||||
|
||||
async function waitForConnection(manager1, manager2, timeout = 10000) {
|
||||
const start = Date.now();
|
||||
|
||||
while (Date.now() - start < timeout) {
|
||||
if (manager1.isConnected() && manager2.isConnected()) {
|
||||
return;
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
throw new Error('Connection timeout');
|
||||
}
|
||||
1224
doc/CONTRIBUTING.md
Normal file
1224
doc/CONTRIBUTING.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user