fastcrypt 1.0.0 fastcrypt: ^1.0.0 copied to clipboard
A high-performance, secure encryption library for Dart, leveraging the powerful **ChaCha20-Poly1305** algorithm.
π FastCrypt #
FastCrypt is a high-performance, secure encryption library for Dart, leveraging the powerful ChaCha20-Poly1305 algorithm. Designed with versatility in mind, FastCrypt can be seamlessly integrated into Dart applications across various platforms, ensuring your data remains confidential and tamper-proof. With a small code you have cutting-edge encryption in your hands:
final fastCrypt = FastCrypt();
// To encrypt a message
final encrypted = fastCrypt.encryptText('Top secret message');
// To decrypt the message
final decrypted = fastCrypt.decryptText(encrypted);
π Table of Contents #
- π FastCrypt
π Introduction #
In the digital age, securing data is paramount. Whether you're developing mobile apps, web applications, or backend services in Dart, ensuring that sensitive information remains protected is crucial. FastCrypt offers a robust solution by implementing the ChaCha20 encryption algorithm combined with Poly1305 for authentication, providing both confidentiality and integrity for your data.
π Why FastCrypt? #
β‘ Superior Performance #
- Software-Optimized: ChaCha20 outperforms AES on platforms without hardware acceleration
- Cross-Platform Excellence: Consistent high performance across mobile, web, and server
- Pure Dart Implementation: No native dependencies or platform-specific code
π Rock-Solid Security #
- Modern Cryptography: Based on the IETF standard RFC 8439
- Complete Protection: Combines encryption (ChaCha20) with authentication (Poly1305)
- Battle-Tested: Used in TLS 1.3 and trusted by major tech companies
π©βπ» Developer-Friendly #
- Simple API: Intuitive methods for both string and byte-based encryption
- Comprehensive Documentation: Clear examples and explanations
- Built-in Safety: Automatic key and nonce generation
π Cryptography Basics #
Before diving into using FastCrypt, it's essential to understand some fundamental cryptographic concepts. Don't worryβwe'll break them down in simple terms!
π Key #
Think of the key as the secret password used to encrypt and decrypt your data. It should be kept confidential; anyone with access to the key can decrypt your data.
- Length: FastCrypt uses a 32-byte (256-bit) key, providing a high level of security.
π Nonce #
A nonce (number used once) is a random value that ensures each encryption operation produces a unique ciphertext, even if the same plaintext and key are used multiple times.
- Length: FastCrypt uses a 12-byte nonce.
π AAD (Additional Authenticated Data) #
AAD allows you to include additional information that you'd like to authenticate but not encrypt. This data is verified during decryption to ensure it hasn't been tampered with.
- Use Case: Including headers or metadata alongside your encrypted data.
π·οΈ Tag #
The tag is a result of the authentication process. It ensures that the ciphertext hasn't been altered and that it originates from a trusted source.
- Length: FastCrypt generates a 16-byte tag.
π Ciphertext #
Ciphertext is the encrypted version of your plaintext data. Without the correct key and nonce, it should be computationally infeasible to revert to the original plaintext.
π Features #
- Authenticated Encryption: Ensures both the confidentiality and integrity of your data.
- Random Key and Nonce Generation: Provides secure random generation methods for keys and nonces.
- Flexible API: Supports both string and byte data types for encryption and decryption.
- Error Handling: Throws specific exceptions (e.g.,
AuthenticationException
) when authentication fails. - Lightweight: No dependencies, ensuring your application remains lean.
βοΈ Installation #
Add FastCrypt to your pubspec.yaml
:
dependencies:
fastcrypt: ^1.0.0
Then, run:
flutter pub get
Note: Replace ^1.0.0
with the latest version available.
π Quick Start #
Encrypting and Decrypting Strings #
Encrypting and decrypting text is straightforward with FastCrypt.
import 'package:fastcrypt/fastcrypt.dart';
void main() {
final crypt = FastCrypt();
String plaintext = "Hello, Dart!";
// Encrypt the plaintext
EncryptedData encrypted = crypt.encryptString(plaintext);
print('Ciphertext: ${encrypted.ciphertext}');
print('Tag: ${encrypted.tag}');
print('Nonce: ${encrypted.nonce}');
// Decrypt the ciphertext
String decrypted = crypt.decryptString(
ciphertext: encrypted.ciphertext,
tag: encrypted.tag,
key: encrypted.key,
nonce: encrypted.nonce,
);
print('Decrypted Text: $decrypted');
}
Encrypting and Decrypting Bytes #
For binary data, use the byte-based methods.
import 'dart:convert';
import 'package:fastcrypt/fastcrypt.dart';
void main() {
final crypt = FastCrypt();
// Sample binary data
List<int> data = utf8.encode("Binary Data Example");
// Encrypt the data
EncryptedData encrypted = crypt.encryptBytes(data);
print('Ciphertext: ${encrypted.ciphertext}');
print('Tag: ${encrypted.tag}');
print('Nonce: ${encrypted.nonce}');
// Decrypt the data
List<int> decryptedBytes = crypt.decryptBytes(
ciphertext: encrypted.ciphertext,
tag: encrypted.tag,
key: encrypted.key,
nonce: encrypted.nonce,
);
String decrypted = utf8.decode(decryptedBytes);
print('Decrypted Data: $decrypted');
}
Generating Keys and Nonces #
FastCrypt provides methods to generate a key and a nonce securely. The encrypt and decrypt methods can also generate these values if not provided. If you prefer to generate them separately, you can use the following:
import 'package:fastcrypt/fastcrypt.dart';
void main() {
// Generate a 32-byte key
List<int> key = FastCrypt.generateKey();
// Generate a 12-byte nonce
List<int> nonce = FastCrypt.generateNonce();
print('Key: $key');
print('Nonce: $nonce');
}
I'll help you add documentation for the ChaCha20Poly1305Encryptor and ChaCha20Poly1305Decryptor classes to your README. Here's how you can include them in your API Reference section:
Stream Transformers #
ChaCha20Poly1305Encryptor
Class
A stream transformer that encrypts data using ChaCha20-Poly1305, processing it in chunks for efficient memory usage.
final encryptor = ChaCha20Poly1305Encryptor(
cipher: cipher,
key: key,
nonce: nonce,
aad: aad, // optional
chunkSize: 64000, // optional, default is 64KB
);
// Use with a stream
final encryptedStream = inputStream.transform(encryptor);
-
Parameters:
cipher
: An instance ofChaCha20Poly1305
key
: A 32-byte encryption keynonce
: A 12-byte nonceaad
: Optional additional authenticated datachunkSize
: Size of chunks to process (default: 64KB)
-
Output Stream Format:
- Nonce (first chunk)
- Encrypted data chunks
- Authentication tag (final chunk)
ChaCha20Poly1305Decryptor
Class
A stream transformer that decrypts data previously encrypted with ChaCha20-Poly1305.
final decryptor = ChaCha20Poly1305Decryptor(
cipher: cipher,
key: key,
aad: aad, // optional
chunkSize: 64000, // optional, default is 64KB
);
// Use with a stream
final decryptedStream = inputStream.transform(decryptor);
-
Parameters:
cipher
: An instance ofChaCha20Poly1305
key
: A 32-byte decryption keyaad
: Optional additional authenticated datachunkSize
: Size of chunks to process (default: 64KB)
-
Input Stream Format:
- Expects data in the format output by
ChaCha20Poly1305Encryptor
- Must include nonce (first 12 bytes) and tag (last 16 bytes)
- Expects data in the format output by
-
Throws:
AuthenticationException
: If the authentication tag verification failsStateError
: If the input stream is emptyArgumentError
: If the input data is too short to contain nonce and tag
𧩠Examples #
Encrypting a Message with AAD #
Including AAD enhances security by binding additional data to the ciphertext.
import 'package:fastcrypt/fastcrypt.dart';
void main() {
final crypt = FastCrypt();
String message = "Sensitive Information";
List<int> aad = utf8.encode("User ID: 12345");
// Encrypt with AAD
EncryptedData encrypted = crypt.encryptString(
message,
aad: aad,
);
print('Ciphertext: ${encrypted.ciphertext}');
print('Tag: ${encrypted.tag}');
print('Nonce: ${encrypted.nonce}');
// Decrypt with AAD
try {
String decrypted = crypt.decryptString(
ciphertext: encrypted.ciphertext,
tag: encrypted.tag,
key: encrypted.key,
nonce: encrypted.nonce,
aad: aad,
);
print('Decrypted Message: $decrypted');
} catch (e) {
print('Decryption failed: $e');
}
}
If the AAD provided during decryption doesn't match the one used during encryption, decryption will fail, ensuring data integrity.
Usage with Streams
import 'package:fastcrypt/fastcrypt.dart';
void main() async {
final cipher = ChaCha20Poly1305();
final key = FastCrypt.generateKey();
final nonce = FastCrypt.generateNonce();
// Create transformers
final encryptor = ChaCha20Poly1305Encryptor(
cipher: cipher,
key: key,
nonce: nonce,
);
final decryptor = ChaCha20Poly1305Decryptor(
cipher: cipher,
key: key,
);
// Example stream encryption and decryption
final inputData = [1, 2, 3, 4, 5];
final inputStream = Stream.fromIterable([inputData]);
// Encrypt
final encryptedStream = inputStream.transform(encryptor);
final encryptedData = await encryptedStream.toList();
// Decrypt
final decryptStream = Stream.fromIterable(encryptedData)
.transform(decryptor);
final decryptedData = await decryptStream.toList();
print('Decrypted: ${decryptedData.first}');
}
π API Reference #
FastCrypt
Class #
Methods
-
generateKey()
Generates a secure 32-byte random key.
static List<int> generateKey();
-
generateNonce()
Generates a secure 12-byte random nonce.
static List<int> generateNonce();
-
encryptString(String plaintext, {List<int>? key, List<int>? nonce, List<int> aad = const []})
Encrypts a plaintext string.
-
Parameters:
plaintext
: The text to encrypt.key
: Optional 32-byte key. If not provided, a new key is generated.nonce
: Optional 12-byte nonce. If not provided, a new nonce is generated.aad
: Optional additional authenticated data.
-
Returns:
EncryptedData
object containing ciphertext, tag, and nonce.
-
-
decryptString({required List<int> ciphertext, required List<int> tag, required List<int> key, required List<int> nonce, List<int> aad = const []})
Decrypts ciphertext to retrieve the original string.
-
Parameters:
ciphertext
: The encrypted data.tag
: The authentication tag.key
: The 32-byte key used during encryption.nonce
: The 12-byte nonce used during encryption.aad
: The same additional authenticated data used during encryption.
-
Returns: Decrypted plaintext string.
-
Throws:
AuthenticationException
if authentication fails.
-
-
encryptBytes(List<int> plaintext, {List<int>? key, List<int>? nonce, List<int> aad = const []})
Encrypts plaintext bytes.
-
Parameters: Same as
encryptString
. -
Returns:
EncryptedData
object.
-
-
decryptBytes({required List<int> ciphertext, required List<int> tag, required List<int> key, required List<int> nonce, List<int> aad = const []})
Decrypts ciphertext bytes.
-
Parameters: Same as
decryptString
. -
Returns: Decrypted plaintext bytes.
-
Throws:
AuthenticationException
if authentication fails.
-
π‘οΈ Security Considerations #
-
Key Management: Always store your encryption keys securely. Consider using secure storage solutions like the device's keychain or secure environment variables.
-
Nonce Uniqueness: Never reuse a nonce with the same key. Reusing nonces can lead to vulnerabilities, potentially exposing your plaintext.
-
Authentication: Always verify the tag during decryption to ensure the data's integrity and authenticity.
-
Randomness: Utilize the provided key and nonce generation methods to ensure cryptographic randomness.
β Best Practices #
-
Never Reuse Keys or Nonces
// Good: Generate new values for each encryption final key = FastCrypt.generateKey(); final nonce = FastCrypt.generateNonce(); // Bad: Reusing values final reusedKey = savedKey; // Don't do this!
-
Secure Key Storage
// Good: Use secure storage final storage = YourSecureStorage(); await storage.write(key: 'encryption_key', value: key); // Bad: Storing in plain text SharedPreferences.setText('key', key); // Don't do this!
-
Handle Errors Properly
try { final decrypted = fastCrypt.decryptString(...); } on AuthenticationException { // Handle tampering attempt logSecurityEvent('Data tampering detected'); } catch (e) { // Handle other errors logError('Encryption error', e); }
π€ Contributing #
Contributions are welcome! Whether it's reporting a bug, suggesting a feature, or submitting a pull request, your involvement helps make FastCrypt better.
- Fork the repository.
- Create your feature branch:
git checkout -b feature/name
. - Commit your changes:
git commit -m 'Add some feature'
. - Push to the branch:
git push origin feature/name
. - Open a pull request.
Please ensure your code adheres to the existing style and includes relevant tests.
π License #
FastCrypt is MIT Licensed.