|
1 |
| -<p align="center"> |
2 |
| -<img width="700px" src="resources/native_crypto.png" style="background-color: rgb(255,255,255)"> |
3 |
| -<h5 align="center">Fast and powerful cryptographic functions for Flutter.</h5> |
4 |
| -</p> |
| 1 | +# NativeCrypto |
5 | 2 |
|
6 |
| -<p align="center"> |
7 |
| -<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis"> |
8 |
| -<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" /> |
9 |
| -</a> |
10 |
| - |
11 |
| -<a href="https://github.com/invertase/melos"> |
12 |
| -<img src="https://img.shields.io/badge/Maintained%20with-melos-f700ff.svg?style=flat-square" alt="Maintained with Melos" /> |
13 |
| -</a> |
14 |
| - |
15 |
| -<a href="https://drone.wyatt-studio.fr/hugo/native-crypto"> |
16 |
| -<img src="https://drone.wyatt-studio.fr/api/badges/hugo/native-crypto/status.svg" alt="Build Status" /> |
17 |
| -</a> |
18 |
| -</p> |
19 |
| - |
20 |
| ---- |
21 |
| - |
22 |
| -[[Changelog]](./CHANGELOG.md) | [[License]](./LICENSE) |
23 |
| - |
24 |
| ---- |
25 |
| - |
26 |
| -## About |
27 |
| - |
28 |
| -The goal of this plugin is to provide a fast and powerful cryptographic functions by calling native libraries. On Android, it uses [javax.cypto](https://developer.android.com/reference/javax/crypto/package-summary), and on iOS, it uses [CommonCrypto](https://opensource.apple.com/source/CommonCrypto/) and [CryptoKit](https://developer.apple.com/documentation/cryptokit/) |
29 |
| - |
30 |
| -I started this projet because I wanted to add cryptographic functions on a Flutter app. But I faced a problem with the well-known [Pointy Castle](https://pub.dev/packages/pointycastle) library: the performance was very poor. Here some benchmarks and comparison: |
31 |
| - |
32 |
| - |
33 |
| - |
34 |
| -For comparison, on a *iPhone 13*, you can encrypt/decrypt a message of **2MiB** in **~5.6s** with PointyCastle and in **~40ms** with NativeCrypto. And on an *OnePlus 5*, you can encrypt/decrypt a message of **50MiB** in **~6min30** with PointyCastle and in less than **~1s** with NativeCrypto. |
35 |
| - |
36 |
| -In short, NativeCrypto is incomparable with PointyCastle. |
37 |
| - |
38 |
| -## Usage |
39 |
| - |
40 |
| -First, check compatibility with your targets. |
41 |
| - |
42 |
| -| iOS | Android | MacOS | Linux | Windows | Web | |
43 |
| -| --- | ------- | ----- | ----- | ------- | --- | |
44 |
| -| ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | |
45 |
| - |
46 |
| -#### Hash |
47 |
| - |
48 |
| -To digest a message, you can use the following function: |
49 |
| - |
50 |
| -```dart |
51 |
| -Uint8List hash = await HashAlgorithm.sha256.digest(message); |
52 |
| -``` |
53 |
| - |
54 |
| -> In NativeCrypto, you can use the following hash functions: SHA-256, SHA-384, SHA-512 |
55 |
| -
|
56 |
| -#### Keys |
57 |
| - |
58 |
| -You can build a `SecretKey` from a utf8, base64, base16 (hex) strings or raw bytes. You can also generate a SecretKey from secure random. |
59 |
| - |
60 |
| -```dart |
61 |
| -SecretKey secretKey = SecretKey(Uint8List.fromList([0x73, 0x65, 0x63, 0x72, 0x65, 0x74])); |
62 |
| -SecretKey secretKey = SecretKey.fromUtf8('secret'); |
63 |
| -SecretKey secretKey = SecretKey.fromBase64('c2VjcmV0'); |
64 |
| -SecretKey secretKey = SecretKey.fromBase16('63657274'); |
65 |
| -SecretKey secretKey = await SecretKey.fromSecureRandom(256); |
66 |
| -``` |
67 |
| - |
68 |
| -#### Key derivation |
69 |
| - |
70 |
| -You can derive a `SecretKey` using **PBKDF2**. |
71 |
| - |
72 |
| -First, you need to initialize a `Pbkdf2` object. |
73 |
| - |
74 |
| -```dart |
75 |
| -Pbkdf2 pbkdf2 = Pbkdf2( |
76 |
| - keyBytesCount: 32, |
77 |
| - iterations: 1000, |
78 |
| - algorithm: HashAlgorithm.sha512, |
79 |
| -); |
80 |
| -``` |
81 |
| - |
82 |
| -Then, you can derive a `SecretKey` from a password and salt. |
83 |
| - |
84 |
| -```dart |
85 |
| -SecretKey secretKey = await pbkdf2.derive(password: password, salt: 'salt'); |
86 |
| -``` |
87 |
| - |
88 |
| -> In NativeCrypto, you can use the following key derivation function: PBKDF2 |
89 |
| -
|
90 |
| -#### Cipher |
91 |
| - |
92 |
| -And now, you can use the `SecretKey` to encrypt/decrypt a message. |
93 |
| - |
94 |
| -First, you need to initialize a `Cipher` object. |
95 |
| - |
96 |
| -```dart |
97 |
| -AES cipher = AES(secretKey); |
98 |
| -``` |
99 |
| - |
100 |
| -Then, you can encrypt your message. |
101 |
| - |
102 |
| -```dart |
103 |
| -CipherTextWrapper wrapper = await cipher.encrypt(message); |
104 |
| -
|
105 |
| -CipherText cipherText = wrapper.unwrap<CipherText>(); |
106 |
| -// same as |
107 |
| -CipherText cipherText = wrapper.single; |
108 |
| -
|
109 |
| -// or |
110 |
| -
|
111 |
| -List<CipherText> cipherTexts = wrapper.unwrap<List<CipherText>>(); |
112 |
| -// same as |
113 |
| -List<CipherText> cipherTexts = wrapper.list; |
114 |
| -``` |
115 |
| - |
116 |
| -After an encryption you obtain a `CipherTextWrapper` which contains `CipherText` or `List<CipherText>` depending on the message size. It's up to you to know how to unwrap the `CipherTextWrapper` depending the chunk size you configured. |
117 |
| - |
118 |
| -Uppon receiving encrypted message, you can decrypt it. |
119 |
| -You have to reconstruct the wrapper before decrypting. |
120 |
| - |
121 |
| -```dart |
122 |
| -CipherTextWrapper wrapper = CipherTextWrapper.fromBytes( |
123 |
| - data, |
124 |
| - ivLength: AESMode.gcm.ivLength, |
125 |
| - tagLength: AESMode.gcm.tagLength, |
126 |
| -); |
127 |
| -``` |
128 |
| - |
129 |
| -Then, you can decrypt your message. |
130 |
| - |
131 |
| -```dart |
132 |
| -Uint8List message = await cipher.decrypt(wrapper); |
133 |
| -``` |
| 3 | +Readme available at [project root](../../README.md). |
0 commit comments