|
1 | | -<!-- |
2 | | -This README describes the package. If you publish this package to pub.dev, |
3 | | -this README's contents appear on the landing page for your package. |
| 1 | +> Minimum Dart SDK 3.10 (Flutter 3.38) with Native Assets/hooks support. |
4 | 2 |
|
5 | | -For information about how to write a good package README, see the guide for |
6 | | -[writing package pages](https://dart.dev/tools/pub/writing-package-pages). |
| 3 | +This package builds OpenSSL from source and exposes its full C surface directly to Dart via FFI. There are no Dart-side abstractions: call the OpenSSL APIs as you would in C, manage memory manually, and follow the official OpenSSL documentation for usage and lifetime rules. |
7 | 4 |
|
8 | | -For general information about developing packages, see the Dart guide for |
9 | | -[creating packages](https://dart.dev/guides/libraries/create-packages) |
10 | | -and the Flutter guide for |
11 | | -[developing packages and plugins](https://flutter.dev/to/develop-packages). |
12 | | ---> |
| 5 | +## What you get |
13 | 6 |
|
14 | | -TODO: Put a short description of the package here that helps potential users |
15 | | -know whether this package might be useful for them. |
16 | | - |
17 | | -## Features |
18 | | - |
19 | | -TODO: List what your package can do. Maybe include images, gifs, or videos. |
| 7 | +- Full OpenSSL C API available in Dart (headers mirrored into FFI bindings). |
| 8 | +- Native assets build step that compiles OpenSSL locally the first time you run the app. |
| 9 | +- No opinionated wrappers; you stay in control of allocation and cleanup. |
20 | 10 |
|
21 | 11 | ## Getting started |
22 | 12 |
|
23 | | -TODO: List prerequisites and provide or point to information on how to |
24 | | -start using the package. |
| 13 | +1) Add the package: `dart pub add openssl` (or add it to your `pubspec.yaml`). |
| 14 | +2) Run your app once to trigger the native build (about 1 minute on first run). |
25 | 15 |
|
26 | | -## Usage |
| 16 | +## Using the bindings |
27 | 17 |
|
28 | | -TODO: Include short and useful examples for package users. Add longer examples |
29 | | -to `/example` folder. |
| 18 | +Import and call OpenSSL functions directly; the generated bindings live under `lib/src/third_party/openssl.g.dart`. |
30 | 19 |
|
31 | 20 | ```dart |
32 | | -const like = 'sample'; |
| 21 | +import 'dart:convert'; |
| 22 | +import 'dart:typed_data'; |
| 23 | +import 'package:ffi/ffi.dart'; |
| 24 | +import 'package:openssl/openssl.dart' as openssl; |
| 25 | +
|
| 26 | +Uint8List aes(Uint8List input, Uint8List key, Uint8List iv, {required bool encrypt}) { |
| 27 | + return using((arena) { |
| 28 | + final ctx = openssl.EVP_CIPHER_CTX_new(); |
| 29 | + final inPtr = arena.allocate<Uint8>(input.isEmpty ? 1 : input.length); |
| 30 | + final keyPtr = arena.allocate<Uint8>(key.length); |
| 31 | + final ivPtr = arena.allocate<Uint8>(iv.length); |
| 32 | + final outPtr = arena.allocate<Uint8>(input.length + openssl.EVP_MAX_BLOCK_LENGTH); |
| 33 | + final outLenPtr = arena.allocate<Int>(2); |
| 34 | +
|
| 35 | + inPtr.asTypedList(input.length).setAll(0, input); |
| 36 | + keyPtr.asTypedList(key.length).setAll(0, key); |
| 37 | + ivPtr.asTypedList(iv.length).setAll(0, iv); |
| 38 | +
|
| 39 | + final initResult = encrypt |
| 40 | + ? openssl.EVP_EncryptInit_ex(ctx, openssl.EVP_aes_256_cbc(), nullptr, keyPtr.cast(), ivPtr.cast()) |
| 41 | + : openssl.EVP_DecryptInit_ex(ctx, openssl.EVP_aes_256_cbc(), nullptr, keyPtr.cast(), ivPtr.cast()); |
| 42 | + if (initResult != 1) throw StateError('init failed'); |
| 43 | +
|
| 44 | + final updateResult = encrypt |
| 45 | + ? openssl.EVP_EncryptUpdate(ctx, outPtr.cast(), outLenPtr, inPtr.cast(), input.length) |
| 46 | + : openssl.EVP_DecryptUpdate(ctx, outPtr.cast(), outLenPtr, inPtr.cast(), input.length); |
| 47 | + if (updateResult != 1) throw StateError('update failed'); |
| 48 | +
|
| 49 | + var outLen = outLenPtr.value; |
| 50 | + final finalResult = encrypt |
| 51 | + ? openssl.EVP_EncryptFinal_ex(ctx, outPtr.elementAt(outLen).cast(), outLenPtr) |
| 52 | + : openssl.EVP_DecryptFinal_ex(ctx, outPtr.elementAt(outLen).cast(), outLenPtr); |
| 53 | + if (finalResult != 1) throw StateError('final failed'); |
| 54 | +
|
| 55 | + outLen += outLenPtr.value; |
| 56 | + return Uint8List.fromList(outPtr.asTypedList(outLen)); |
| 57 | + }); |
| 58 | +} |
| 59 | +
|
| 60 | +void main() { |
| 61 | + final key = utf8.encode('Nc92PMoPjcIls5QoXeki5yIPuhjjWMcx'); |
| 62 | + final iv = utf8.encode('1234567890123456'); |
| 63 | + final plaintext = utf8.encode('Secret message for AES-256-CBC'); |
| 64 | +
|
| 65 | + final encrypted = aes(plaintext, Uint8List.fromList(key), Uint8List.fromList(iv), encrypt: true); |
| 66 | + final decrypted = aes(encrypted, Uint8List.fromList(key), Uint8List.fromList(iv), encrypt: false); |
| 67 | +
|
| 68 | + print('cipher (b64): ${base64.encode(encrypted)}'); |
| 69 | + print('roundtrip: ${utf8.decode(decrypted)}'); |
| 70 | +} |
33 | 71 | ``` |
34 | 72 |
|
35 | | -## Additional information |
| 73 | +Remember: follow OpenSSL docs for allocation/free patterns (`OPENSSL_free`, `EVP_*` lifecycle, etc.). |
| 74 | + |
| 75 | +## Build notes and roadmap |
36 | 76 |
|
37 | | -TODO: Tell users more about the package: where to find more information, how to |
38 | | -contribute to the package, how to file issues, what response they can expect |
39 | | -from the package authors, and more. |
| 77 | +- First build compiles OpenSSL; subsequent runs are faster. The goal is to ship precompiled binaries later to skip this step. |
| 78 | +- Native assets require Flutter 3.38+/Dart 3.10+ to run the hook pipeline. |
40 | 79 |
|
| 80 | +## Contributing |
41 | 81 |
|
42 | | -`git submodule update --init` |
| 82 | +For local builds, regenerating bindings, and working with the OpenSSL submodule, see `contrib.md`. |
0 commit comments