bariew / whatsapp-crypto
PSR-7 stream decorators for WhatsApp-style encryption and decryption
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/bariew/whatsapp-crypto
Requires
- php: ^7.4|^8.0
- ext-hash: *
- ext-openssl: *
- guzzlehttp/psr7: ^2.0
- psr/http-message: ^1.0|^2.0
Requires (Dev)
- phpunit/phpunit: ^9.0|^10.0
README
PSR-7 stream decorators for WhatsApp-style encryption and decryption of media files. This library implements the same encryption algorithm used by WhatsApp to encrypt images, videos, audio, and documents.
Features
- Stream-based encryption/decryption: Uses PSR-7 stream decorators for memory-efficient processing
- WhatsApp-compatible: Implements the exact same encryption algorithm as WhatsApp
- Chunk-based MAC generation: Supports sidecar file generation for streaming scenarios
- No external dependencies: Only requires PHP extensions that are commonly available
- Well-tested: Comprehensive unit and integration tests with sample files
Installation
Install the package via Composer:
composer require bariew/whatsapp-crypto
Requirements
- PHP 7.4 or higher
ext-opensslextensionext-hashextensionpsr/http-message(^1.0 or ^2.0)guzzlehttp/psr7(^2.0)
Quick Start
Encrypting a File
use GuzzleHttp\Psr7\Stream; use bariew\WhatsAppCrypto\Factory\EncryptedStreamFactory; use bariew\WhatsAppCrypto\Enum\MediaType; // Your 32-byte mediaKey (raw binary) $mediaKey = random_bytes(32); // Open the source file and encrypted output $sourceStream = fopen('/path/to/original/file.jpg', 'rb'); $encryptedStream = fopen('/path/to/encrypted/file.encrypted', 'wb'); $encryptedPsr7Stream = new Stream($encryptedStream); // Create encrypted stream $encryptor = new EncryptedStreamFactory(); $encrypted = $encryptor->create($encryptedPsr7Stream, $mediaKey, MediaType::IMAGE); // Encrypt the file $encrypted->readAndWrite(new Stream($sourceStream));
Decrypting a File
use GuzzleHttp\Psr7\Stream; use bariew\WhatsAppCrypto\Factory\DecryptedStreamFactory; use bariew\WhatsAppCrypto\Enum\MediaType; // Your 32-byte mediaKey (raw binary) $mediaKey = file_get_contents('/path/to/file.key'); $decryptedStream = fopen('/path/to/decrypted/file.jpg', 'wb'); // Create decrypted stream $decryptor = new DecryptedStreamFactory(); $decrypted = $decryptor->createFromFile('/path/to/encrypted/file.encrypted', $mediaKey, MediaType::IMAGE); // Decrypt the file while (!$decrypted->eof()) { fwrite($decryptedStream, $decrypted->read(8192)); } $decrypted->close();
Testing
Run the test suite:
composer test
The project includes integration tests with sample files for AUDIO, IMAGE, and VIDEO media types.
Sample Files
The samples/ directory contains test files:
*.original- Original unencrypted files*.encrypted- Encrypted versions using WhatsApp-compatible encryption*.key- The 32-byte mediaKeys used for encryptionVIDEO.sidecar- Example sidecar file for chunk-based verification
Security Considerations
- MAC Truncation: WhatsApp uses the first 10 bytes of HMAC-SHA256. This is a deliberate design choice for compactness, though it reduces the theoretical security margin.
- Timing-Safe Comparison: The library uses
hash_equals()for MAC verification to prevent timing attacks. - Key Management: Keep your mediaKeys secure. Anyone with the mediaKey can decrypt the corresponding media.
License
This package is open-source software licensed under the MIT license.
Credits
This implementation is based on the WhatsApp encryption protocol as documented in various reverse-engineering efforts and the Signal protocol specifications.