874 lines
21 KiB
Markdown
874 lines
21 KiB
Markdown
# CipherGuard SDK API Documentation
|
||
|
||
## 概述
|
||
|
||
CipherGuard SDK 是一個 Flutter 外掛,提供完整的端對端加密(E2EE)解決方案。該 SDK 簡化了加密整合流程,提供 RSA 金鑰管理、AES 會話金鑰管理、訊息加解密等功能。
|
||
|
||
### 主要特性
|
||
|
||
- **統一 API 介面** - 簡潔的抽象類設計,易於整合和使用
|
||
- **跨平台加密** - 所有加密邏輯在 Flutter 層實現,Android 和 iOS 保持一致
|
||
- **RSA 金鑰管理** - 生成、加密/解密私鑰
|
||
- **AES 會話金鑰** - 每個聊天室獨立的安全會話金鑰
|
||
- **訊息加解密** - 使用 AES-CTR 模式進行高效加密
|
||
- **推送通知解密** - 支援 AES-GCM 模式解密推播通知
|
||
- **原生平台同步** - 支援 iOS App Group 同步加密金鑰
|
||
|
||
---
|
||
|
||
## Demo螢幕截圖
|
||
|
||
以下為 CipherGuard SDK 的範例應用程式截圖,展示各種功能設定介面:
|
||
|
||
<img src="https://raw.githubusercontent.com/leechupe/qrcode_sample/master/lib/cipher.PNG" width="100" alt="CipherGuard SDK Example">
|
||
|
||
圖片說明:
|
||
- 生成 RSA 金鑰對:產生 RSA Public / Private Key
|
||
- 加密私鑰:使用使用者密碼對 RSA 私鑰進行加密
|
||
- 解密私鑰:驗證加密後私鑰是否能正確還原
|
||
- 生成會話金鑰:產生聊天室專用的 AES Session Key
|
||
- 加密會話金鑰:使用 RSA 公鑰加密 Session Key(模擬金鑰交換)
|
||
- 解密會話金鑰:使用 RSA 私鑰解密 Session Key
|
||
- 加密訊息:使用 AES-CTR 模式加密文字訊息
|
||
- 解密訊息:解密加密後的訊息內容
|
||
- 畫面中顯示 解密結果:Hello, this is a secret message!,代表端對端加解密流程成功
|
||
- 同步加密金鑰到原生:將聊天室金鑰同步至原生平台(例如 iOS App Group)
|
||
- 用於支援 Notification Service Extension 或其他原生模組存取加密金鑰
|
||
- 設定 AES_SECRET:設定用於推送通知 AES-GCM 解密的密鑰
|
||
- 對應實際 APNS 推送通知加密 / 解密使用情境
|
||
|
||
---
|
||
|
||
## API 總覽
|
||
|
||
<style>
|
||
table { font-size: 14px; }
|
||
td, th { padding: 8px; }
|
||
</style>
|
||
|
||
### 方法(Methods)
|
||
|
||
| 方法 | 回傳類型 | 說明 |
|
||
|------|----------|------|
|
||
| `platformVersion()` | `Future<String?>` | 獲取平台版本 |
|
||
| `generateRsaKeyPair({int keySize = 1024})` | `Future<RsaKeyPair>` | 生成 RSA 金鑰對 |
|
||
| `encryptPrivateKey({required String privateKey, required String password})` | `Future<String>` | 用密碼加密私鑰 |
|
||
| `decryptPrivateKey({required String encryptedPrivateKey, required String password})` | `Future<String>` | 解密私鑰 |
|
||
| `generateSessionKey({int initialRound = 1})` | `Future<SessionKey>` | 生成 AES 會話金鑰 |
|
||
| `encryptSessionKey({required String sessionKey, required String publicKey})` | `Future<String>` | 用 RSA 公鑰加密會話金鑰 |
|
||
| `decryptSessionKey({required String encryptedSessionKey, required String privateKey})` | `Future<String>` | 用 RSA 私鑰解密會話金鑰 |
|
||
| `encryptMessage({required String plaintext, required String sessionKey, required int round})` | `Future<EncryptedMessage>` | 加密訊息 |
|
||
| `decryptMessage({required String encryptedData, required String sessionKey, required int round})` | `Future<String>` | 解密訊息 |
|
||
| `syncEncryptionKey({required String chatId, required int activeRound, required int round, required String activeKeySingle})` |, required bool is `Future<void>` | 同步加密金鑰到原生平台 |
|
||
| `syncAllEncryptionKeys({required Map<String, Map<String, dynamic>> chatMap})` | `Future<void>` | 批量同步所有加密金鑰 |
|
||
| `setAesSecret({required String aesSecret})` | `Future<void>` | 設置 AES_SECRET |
|
||
| `decryptPushNotification({required String encryptedData})` | `Future<String?>` | 解密推送通知 |
|
||
|
||
### 實體類別(Entities)
|
||
|
||
| 類別 | 說明 |
|
||
|------|------|
|
||
| `RsaKeyPair` | RSA 金鑰對(公鑰/私鑰) |
|
||
| `SessionKey` | AES 會話金鑰 |
|
||
| `EncryptedMessage` | 加密訊息 |
|
||
|
||
---
|
||
|
||
## 安裝
|
||
|
||
在 `pubspec.yaml` 中新增依賴:
|
||
|
||
```yaml
|
||
dependencies:
|
||
cipher_guard_sdk: ^1.0.0
|
||
```
|
||
|
||
### Flutter 安裝
|
||
|
||
執行以下命令獲取依賴:
|
||
|
||
```bash
|
||
flutter pub get
|
||
```
|
||
|
||
### 初始化
|
||
|
||
在 `main.dart` 中初始化 SDK:
|
||
|
||
```dart
|
||
import 'package:cipher_guard_sdk/cipher_guard_sdk.dart';
|
||
```
|
||
|
||
---
|
||
|
||
## 快速開始
|
||
|
||
### 1. 初始化 SDK
|
||
|
||
```dart
|
||
import 'package:flutter/material.dart';
|
||
import 'package:cipher_guard_sdk/cipher_guard_sdk.dart';
|
||
|
||
void main() {
|
||
runApp(const MyApp());
|
||
}
|
||
|
||
class MyApp extends StatefulWidget {
|
||
const MyApp({super.key});
|
||
|
||
@override
|
||
State<MyApp> createState() => _MyAppState();
|
||
}
|
||
|
||
class _MyAppState extends State<MyApp> {
|
||
final CipherGuardSdkApi cipherGuard = CipherGuardSdkApi();
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_testEncryption();
|
||
}
|
||
|
||
Future<void> _testEncryption() async {
|
||
try {
|
||
// 1. 生成 RSA 金鑰對
|
||
final keyPair = await cipherGuard.generateRsaKeyPair(keySize: 1024);
|
||
print('Public Key: ${keyPair.publicKey}');
|
||
print('Private Key: ${keyPair.privateKey}');
|
||
|
||
// 2. 用密碼加密私鑰
|
||
const password = 'user_password_123';
|
||
final encryptedPrivateKey = await cipherGuard.encryptPrivateKey(
|
||
privateKey: keyPair.privateKey,
|
||
password: password,
|
||
);
|
||
print('Encrypted Private Key: $encryptedPrivateKey');
|
||
|
||
// 3. 解密私鑰
|
||
final decryptedPrivateKey = await cipherGuard.decryptPrivateKey(
|
||
encryptedPrivateKey: encryptedPrivateKey,
|
||
password: password,
|
||
);
|
||
print('Decrypted Private Key: $decryptedPrivateKey');
|
||
|
||
// 4. 生成會話金鑰
|
||
final sessionKey = await cipherGuard.generateSessionKey(initialRound: 1);
|
||
print('Session Key: ${sessionKey.key}');
|
||
print('Session Round: ${sessionKey.round}');
|
||
|
||
// 5. 用 RSA 公鑰加密會話金鑰
|
||
final encryptedSessionKey = await cipherGuard.encryptSessionKey(
|
||
sessionKey: sessionKey.key,
|
||
publicKey: keyPair.publicKey,
|
||
);
|
||
print('Encrypted Session Key: $encryptedSessionKey');
|
||
|
||
// 6. 用 RSA 私鑰解密會話金鑰
|
||
final decryptedSessionKey = await cipherGuard.decryptSessionKey(
|
||
encryptedSessionKey: encryptedSessionKey,
|
||
privateKey: keyPair.privateKey,
|
||
);
|
||
print('Decrypted Session Key: $decryptedSessionKey');
|
||
|
||
// 7. 加密訊息
|
||
const message = 'Hello, this is a secret message!';
|
||
final encryptedMessage = await cipherGuard.encryptMessage(
|
||
plaintext: message,
|
||
sessionKey: sessionKey.key,
|
||
round: sessionKey.round,
|
||
);
|
||
print('Encrypted Message: ${encryptedMessage.data}');
|
||
print('Message Round: ${encryptedMessage.round}');
|
||
|
||
// 8. 解密訊息
|
||
final decryptedMessage = await cipherGuard.decryptMessage(
|
||
encryptedData: encryptedMessage.data,
|
||
sessionKey: sessionKey.key,
|
||
round: encryptedMessage.round,
|
||
);
|
||
print('Decrypted Message: $decryptedMessage');
|
||
|
||
// 9. 設置 AES_SECRET 用於推送解密
|
||
await cipherGuard.setAesSecret(aesSecret: 'your_aes_secret_key_here');
|
||
|
||
print('All encryption tests passed!');
|
||
} catch (e) {
|
||
print('Encryption test failed: $e');
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return MaterialApp(
|
||
home: Scaffold(
|
||
appBar: AppBar(title: const Text('CipherGuard SDK Demo')),
|
||
body: const Center(
|
||
child: Text('CipherGuard SDK Demo'),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## CipherGuardSdkApi 介面
|
||
|
||
`CipherGuardSdkApi` 是 SDK 的核心抽象類,提供了所有加密相關功能。
|
||
|
||
### 方法
|
||
|
||
#### `platformVersion`
|
||
|
||
```dart
|
||
Future<String?> platformVersion();
|
||
```
|
||
|
||
**描述**:獲取當前平台版本。
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final version = await cipherGuard.platformVersion();
|
||
print('Platform Version: $version');
|
||
```
|
||
|
||
---
|
||
|
||
#### `generateRsaKeyPair`
|
||
|
||
```dart
|
||
Future<RsaKeyPair> generateRsaKeyPair({int keySize = 1024});
|
||
```
|
||
|
||
**描述**:生成 RSA 金鑰對。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 預設值 | 說明 |
|
||
|------|------|--------|------|
|
||
| `keySize` | `int` | 1024 | RSA 金鑰長度(支援 1024、2048) |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final keyPair = await cipherGuard.generateRsaKeyPair(keySize: 2048);
|
||
print('Public Key: ${keyPair.publicKey}');
|
||
print('Private Key: ${keyPair.privateKey}');
|
||
```
|
||
|
||
**返回結果**:
|
||
|
||
| 屬性 | 類型 | 說明 |
|
||
|------|------|------|
|
||
| `publicKey` | `String` | PEM 格式的公鑰 |
|
||
| `privateKey` | `String` | PEM 格式的私鑰 |
|
||
|
||
---
|
||
|
||
#### `encryptPrivateKey`
|
||
|
||
```dart
|
||
Future<String> encryptPrivateKey({
|
||
required String privateKey,
|
||
required String password,
|
||
});
|
||
```
|
||
|
||
**描述**:使用密碼對 RSA 私鑰進行加密。採用 AES-CBC 模式,使用 MD5(password) 作為金鑰。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 必填 | 說明 |
|
||
|------|------|------|------|
|
||
| `privateKey` | `String` | 是 | PEM 格式的私鑰 |
|
||
| `password` | `String` | 是 | 用於加密的密碼 |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final encryptedKey = await cipherGuard.encryptPrivateKey(
|
||
privateKey: keyPair.privateKey,
|
||
password: 'user_password',
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
#### `decryptPrivateKey`
|
||
|
||
```dart
|
||
Future<String> decryptPrivateKey({
|
||
required String encryptedPrivateKey,
|
||
required String password,
|
||
});
|
||
```
|
||
|
||
**描述**:使用密碼解密 RSA 私鑰。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 必填 | 說明 |
|
||
|------|------|------|------|
|
||
| `encryptedPrivateKey` | `String` | 是 | Base64 編碼的加密私鑰 |
|
||
| `password` | `String` | 是 | 用於解密的密碼 |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final privateKey = await cipherGuard.decryptPrivateKey(
|
||
encryptedPrivateKey: encryptedKey,
|
||
password: 'user_password',
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
#### `generateSessionKey`
|
||
|
||
```dart
|
||
Future<SessionKey> generateSessionKey({int initialRound = 1});
|
||
```
|
||
|
||
**描述**:生成 AES 會話金鑰(32 字節隨機金鑰)。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 預設值 | 說明 |
|
||
|------|------|--------|------|
|
||
| `initialRound` | `int` | 1 | 初始 round 值 |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final sessionKey = await cipherGuard.generateSessionKey(initialRound: 1);
|
||
print('Key: ${sessionKey.key}');
|
||
print('Round: ${sessionKey.round}');
|
||
```
|
||
|
||
**返回結果**:
|
||
|
||
| 屬性 | 類型 | 說明 |
|
||
|------|------|------|
|
||
| `key` | `String` | Base64 編碼的 32 字節會話金鑰 |
|
||
| `round` | `int` | 金鑰 round 值 |
|
||
|
||
---
|
||
|
||
#### `encryptSessionKey`
|
||
|
||
```dart
|
||
Future<String> encryptSessionKey({
|
||
required String sessionKey,
|
||
required String publicKey,
|
||
});
|
||
```
|
||
|
||
**描述**:使用 RSA 公鑰加密會話金鑰。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 必填 | 說明 |
|
||
|------|------|------|------|
|
||
| `sessionKey` | `String` | 是 | Base64 編碼的會話金鑰 |
|
||
| `publicKey` | `String` | 是 | PEM 格式的 RSA 公鑰 |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final encryptedSessionKey = await cipherGuard.encryptSessionKey(
|
||
sessionKey: sessionKey.key,
|
||
publicKey: keyPair.publicKey,
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
#### `decryptSessionKey`
|
||
|
||
```dart
|
||
Future<String> decryptSessionKey({
|
||
required String encryptedSessionKey,
|
||
required String privateKey,
|
||
});
|
||
```
|
||
|
||
**描述**:使用 RSA 私鑰解密會話金鑰。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 必填 | 說明 |
|
||
|------|------|------|------|
|
||
| `encryptedSessionKey` | `String` | 是 | Base64 編碼的加密會話金鑰 |
|
||
| `privateKey` | `String` | 是 | PEM 格式的 RSA 私鑰 |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final decryptedKey = await cipherGuard.decryptSessionKey(
|
||
encryptedSessionKey: encryptedSessionKey,
|
||
privateKey: keyPair.privateKey,
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
#### `encryptMessage`
|
||
|
||
```dart
|
||
Future<EncryptedMessage> encryptMessage({
|
||
required String plaintext,
|
||
required String sessionKey,
|
||
required int round,
|
||
});
|
||
```
|
||
|
||
**描述**:使用 AES-CTR 模式加密訊息。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 必填 | 說明 |
|
||
|------|------|------|------|
|
||
| `plaintext` | `String` | 是 | 要加密的原始訊息 |
|
||
| `sessionKey` | `String` | 是 | Base64 編碼的會話金鑰 |
|
||
| `round` | `int` | 是 | 金鑰 round 值 |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final encryptedMessage = await cipherGuard.encryptMessage(
|
||
plaintext: 'Hello, World!',
|
||
sessionKey: sessionKey.key,
|
||
round: sessionKey.round,
|
||
);
|
||
print('Encrypted Data: ${encryptedMessage.data}');
|
||
```
|
||
|
||
**返回結果**:
|
||
|
||
| 屬性 | 類型 | 說明 |
|
||
|------|------|------|
|
||
| `round` | `int` | 金鑰 round 值 |
|
||
| `data` | `String` | Base64 編碼的加密內容(IV + 加密資料) |
|
||
|
||
---
|
||
|
||
#### `decryptMessage`
|
||
|
||
```dart
|
||
Future<String> decryptMessage({
|
||
required String encryptedData,
|
||
required String sessionKey,
|
||
required int round,
|
||
});
|
||
```
|
||
|
||
**描述**:使用 AES-CTR 模式解密訊息。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 必填 | 說明 |
|
||
|------|------|------|------|
|
||
| `encryptedData` | `String` | 是 | Base64 編碼的加密資料 |
|
||
| `sessionKey` | `String` | 是 | Base64 編碼的會話金鑰 |
|
||
| `round` | `int` | 是 | 金鑰 round 值 |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final decrypted = await cipherGuard.decryptMessage(
|
||
encryptedData: encryptedMessage.data,
|
||
sessionKey: sessionKey.key,
|
||
round: encryptedMessage.round,
|
||
);
|
||
print('Decrypted: $decrypted');
|
||
```
|
||
|
||
---
|
||
|
||
#### `syncEncryptionKey`
|
||
|
||
```dart
|
||
Future<void> syncEncryptionKey({
|
||
required String chatId,
|
||
required int activeRound,
|
||
required int round,
|
||
required String activeKey,
|
||
required bool isSingle,
|
||
});
|
||
```
|
||
|
||
**描述**:同步單個聊天室的加密金鑰到原生平台(iOS App Group)。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 必填 | 說明 |
|
||
|------|------|------|------|
|
||
| `chatId` | `String` | 是 | 聊天室 ID |
|
||
| `activeRound` | `int` | 是 | 當前活躍的 round 值 |
|
||
| `round` | `int` | 是 | round 值 |
|
||
| `activeKey` | `String` | 是 | 活躍的加密金鑰 |
|
||
| `isSingle` | `bool` | 是 | 是否為單聊 |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
await cipherGuard.syncEncryptionKey(
|
||
chatId: 'chat_123',
|
||
activeRound: 1,
|
||
round: 1,
|
||
activeKey: sessionKey.key,
|
||
isSingle: false,
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
#### `syncAllEncryptionKeys`
|
||
|
||
```dart
|
||
Future<void> syncAllEncryptionKeys({
|
||
required Map<String, Map<String, dynamic>> chatMap,
|
||
});
|
||
```
|
||
|
||
**描述**:批量同步所有加密聊天室的金鑰到原生平台。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 必填 | 說明 |
|
||
|------|------|------|------|
|
||
| `chatMap` | `Map<String, Map<String, dynamic>>` | 是 | 聊天室金鑰映射 |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final chatMap = {
|
||
'chat_1': {
|
||
'activeKey': sessionKey.key,
|
||
'activeRound': 1,
|
||
'round': 1,
|
||
'isSingle': false,
|
||
},
|
||
'chat_2': {
|
||
'activeKey': anotherKey.key,
|
||
'activeRound': 1,
|
||
'round': 1,
|
||
'isSingle': true,
|
||
},
|
||
};
|
||
|
||
await cipherGuard.syncAllEncryptionKeys(chatMap: chatMap);
|
||
```
|
||
|
||
---
|
||
|
||
#### `setAesSecret`
|
||
|
||
```dart
|
||
Future<void> setAesSecret({required String aesSecret});
|
||
```
|
||
|
||
**描述**:設置 AES_SECRET(用於推送通知解密)。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 必填 | 說明 |
|
||
|------|------|------|------|
|
||
| `aesSecret` | `String` | 是 | AES 密鑰(十六進制字串) |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
await cipherGuard.setAesSecret(aesSecret: '0123456789abcdef');
|
||
```
|
||
|
||
---
|
||
|
||
#### `decryptPushNotification`
|
||
|
||
```dart
|
||
Future<String?> decryptPushNotification({required String encryptedData});
|
||
```
|
||
|
||
**描述**:解密 APNS 推送通知內容。使用 AES-GCM 模式。
|
||
|
||
**參數**:
|
||
|
||
| 參數 | 類型 | 必填 | 說明 |
|
||
|------|------|------|------|
|
||
| `encryptedData` | `String` | 是 | Base64 編碼的加密資料 |
|
||
|
||
**使用範例**:
|
||
```dart
|
||
final decrypted = await cipherGuard.decryptPushNotification(
|
||
encryptedData: pushNotificationData,
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## 實體類別
|
||
|
||
### RsaKeyPair
|
||
|
||
```dart
|
||
class RsaKeyPair {
|
||
final String publicKey;
|
||
final String privateKey;
|
||
|
||
const RsaKeyPair({
|
||
required this.publicKey,
|
||
required this.privateKey,
|
||
});
|
||
|
||
/// 檢查金鑰對是否有效
|
||
bool get isValid => publicKey.isNotEmpty && privateKey.isNotEmpty;
|
||
}
|
||
```
|
||
|
||
**屬性說明**:
|
||
|
||
| 屬性 | 類型 | 說明 |
|
||
|------|------|------|
|
||
| `publicKey` | `String` | PEM 格式的 RSA 公鑰 |
|
||
| `privateKey` | `String` | PEM 格式的 RSA 私鑰 |
|
||
| `isValid` | `bool` | 金鑰對是否有效 |
|
||
|
||
---
|
||
|
||
### SessionKey
|
||
|
||
```dart
|
||
class SessionKey {
|
||
final String key; // Base64 編碼的 32 字節金鑰
|
||
final int round; // 金鑰輪換 round 值
|
||
|
||
const SessionKey({
|
||
required this.key,
|
||
required this.round,
|
||
});
|
||
}
|
||
```
|
||
|
||
**屬性說明**:
|
||
|
||
| 屬性 | 類型 | 說明 |
|
||
|------|------|------|
|
||
| `key` | `String` | Base64 編碼的 32 字節 AES 會話金鑰 |
|
||
| `round` | `int` | 金鑰輪換 round 值 |
|
||
|
||
---
|
||
|
||
### EncryptedMessage
|
||
|
||
```dart
|
||
class EncryptedMessage {
|
||
final int round; // 金鑰輪換 round 值
|
||
final String data; // Base64 編碼的加密內容
|
||
|
||
const EncryptedMessage({
|
||
required this.round,
|
||
required this.data,
|
||
});
|
||
|
||
/// 從 JSON 創建
|
||
factory EncryptedMessage.fromJson(Map<String, dynamic> json) {
|
||
return EncryptedMessage(
|
||
round: json['round'] as int,
|
||
data: json['data'] as String,
|
||
);
|
||
}
|
||
|
||
/// 轉換為 JSON
|
||
Map<String, dynamic> toJson() {
|
||
return {
|
||
'round': round,
|
||
'data': data,
|
||
};
|
||
}
|
||
}
|
||
```
|
||
|
||
**屬性說明**:
|
||
|
||
| 屬性 | 類型 | 說明 |
|
||
|------|------|------|
|
||
| `round` | `int` | 金鑰 round 值 |
|
||
| `data` | `String` | Base64 編碼的加密內容 |
|
||
|
||
---
|
||
|
||
## 加密流程
|
||
|
||
### 訊息加密流程
|
||
|
||
```
|
||
1. 用戶 A 生成 RSA 金鑰對
|
||
├── publicKey_A (公開)
|
||
└── privateKey_A (保密,用密碼加密存儲)
|
||
|
||
2. 用戶 A 生成會話金鑰
|
||
└── sessionKey (每個聊天室獨立)
|
||
|
||
3. 用戶 A 用 RSA publicKey_B 加密會話金鑰
|
||
└── encryptedSessionKey (傳送給用戶 B)
|
||
|
||
4. 用戶 A 加密訊息
|
||
└── encryptMessage(plaintext, sessionKey, round)
|
||
└── EncryptedMessage(round, data)
|
||
```
|
||
|
||
### 訊息解密流程
|
||
|
||
```
|
||
1. 用戶 B 收到加密的會話金鑰
|
||
└── decryptSessionKey(encryptedSessionKey, privateKey_B)
|
||
|
||
2. 用戶 B 解密訊息
|
||
└── decryptMessage(encryptedData, sessionKey, round)
|
||
└── plaintext
|
||
```
|
||
|
||
---
|
||
|
||
## iOS 設定
|
||
|
||
### App Groups 設定
|
||
|
||
用於加密金鑰同步,需要設定 App Groups:
|
||
|
||
在 Xcode 中選擇你的主 Target:
|
||
- **Signing & Capabilities** → **+ Capability** → **App Groups**
|
||
- 建立名為 `group.com.example.cipherguard` 的 App Group
|
||
|
||
---
|
||
|
||
## Android 設定
|
||
|
||
無需額外設定。SDK 使用 Flutter 層的加密邏輯。
|
||
|
||
---
|
||
|
||
## 完整範例
|
||
|
||
以下是一個完整的端對端加密聊天整合範例:
|
||
|
||
```dart
|
||
import 'package:flutter/material.dart';
|
||
import 'package:cipher_guard_sdk/cipher_guard_sdk.dart';
|
||
|
||
void main() {
|
||
runApp(const ChatApp());
|
||
}
|
||
|
||
class ChatApp extends StatefulWidget {
|
||
const ChatApp({super.key});
|
||
|
||
@override
|
||
State<ChatApp> createState() => _ChatAppState();
|
||
}
|
||
|
||
class _ChatAppState extends State<ChatApp> {
|
||
final CipherGuardSdkApi cipherGuard = CipherGuardSdkApi();
|
||
|
||
// 用戶的金鑰對
|
||
RsaKeyPair? _keyPair;
|
||
// 聊天室的會話金鑰
|
||
SessionKey? _sessionKey;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_initializeEncryption();
|
||
}
|
||
|
||
Future<void> _initializeEncryption() async {
|
||
// 生成 RSA 金鑰對
|
||
_keyPair = await cipherGuard.generateRsaKeyPair(keySize: 2048);
|
||
|
||
// 生成會話金鑰
|
||
_sessionKey = await cipherGuard.generateSessionKey(initialRound: 1);
|
||
|
||
setState(() {});
|
||
}
|
||
|
||
Future<void> _sendMessage(String message) async {
|
||
if (_sessionKey == null) return;
|
||
|
||
// 加密訊息
|
||
final encrypted = await cipherGuard.encryptMessage(
|
||
plaintext: message,
|
||
sessionKey: _sessionKey!.key,
|
||
round: _sessionKey!.round,
|
||
);
|
||
|
||
// 發送 encrypted.round 和 encrypted.data 給對方
|
||
print('Sending encrypted message: ${encrypted.data}');
|
||
}
|
||
|
||
Future<String> _receiveMessage(String encryptedData, int round) async {
|
||
if (_sessionKey == null) return '';
|
||
|
||
// 解密訊息
|
||
final decrypted = await cipherGuard.decryptMessage(
|
||
encryptedData: encryptedData,
|
||
sessionKey: _sessionKey!.key,
|
||
round: round,
|
||
);
|
||
|
||
return decrypted;
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return MaterialApp(
|
||
home: Scaffold(
|
||
appBar: AppBar(title: const Text('E2E Chat Demo')),
|
||
body: Center(
|
||
child: _keyPair == null
|
||
? const CircularProgressIndicator()
|
||
: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Text('RSA Key Generated: ${_keyPair!.publicKey.substring(0, 50)}...'),
|
||
const SizedBox(height: 20),
|
||
Text('Session Key: ${_sessionKey!.key.substring(0, 20)}...'),
|
||
const SizedBox(height: 20),
|
||
ElevatedButton(
|
||
onPressed: () => _sendMessage('Hello, World!'),
|
||
child: const Text('Send Encrypted Message'),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 安全性說明
|
||
|
||
### 金鑰管理
|
||
|
||
1. **RSA 私鑰保護**:私鑰必須使用強密碼加密後存儲
|
||
2. **會話金鑰**:每個聊天室應使用獨立的會話金鑰
|
||
3. **金鑰輪換**:透過 round 值實現金鑰輪換
|
||
|
||
### 加密算法
|
||
|
||
| 功能 | 算法 | 模式 | 說明 |
|
||
|------|------|------|------|
|
||
| RSA 金鑰生成 | RSA | - | 支援 1024/2048 位元 |
|
||
| 私鑰加密 | AES | CBC | 使用 MD5(password) 作為金鑰 |
|
||
| 會話金鑰加密 | RSA | PKCS1 | 標準 RSA 加密 |
|
||
| 訊息加密 | AES | CTR | 高效流式加密 |
|
||
| 推送解密 | AES | GCM | 帶認證的加密 |
|
||
|
||
---
|
||
|
||
## 版本歷史
|
||
|
||
| 版本 | 日期 | 說明 |
|
||
|-------|-----------|--------|
|
||
| 0.0.1 | 01/30/2026 | 相關金鑰生成 |
|
||
|
||
---
|
||
|
||
## 許可協議
|
||
|
||
MIT License
|
||
|