378 lines
12 KiB
Dart
378 lines
12 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'dart:async';
|
|
|
|
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> {
|
|
String _platformVersion = 'Unknown';
|
|
final CipherGuardSdkApi _sdk = CipherGuardSdkApi();
|
|
|
|
// 加密相關狀態
|
|
RsaKeyPair? _keyPair;
|
|
String? _encryptedPrivateKey;
|
|
SessionKey? _sessionKey;
|
|
EncryptedMessage? _encryptedMessage;
|
|
String _decryptedMessage = '';
|
|
String _statusMessage = '';
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
initPlatformState();
|
|
}
|
|
|
|
Future<void> initPlatformState() async {
|
|
String platformVersion;
|
|
try {
|
|
platformVersion = (await _sdk.platformVersion()) ?? 'Unknown platform version';
|
|
} catch (e) {
|
|
platformVersion = 'Failed to get platform version: $e';
|
|
}
|
|
|
|
if (!mounted) return;
|
|
|
|
setState(() {
|
|
_platformVersion = platformVersion;
|
|
});
|
|
}
|
|
|
|
// ==================== RSA 金鑰管理 ====================
|
|
|
|
Future<void> _generateRsaKeyPair() async
|
|
{
|
|
setState(() => _statusMessage = 'Generating RSA key pair...');
|
|
try {
|
|
final keyPair = await _sdk.generateRsaKeyPair(keySize: 1024);
|
|
setState(() {
|
|
_keyPair = keyPair;
|
|
_statusMessage = 'RSA key pair generated successfully!\nPublic Key: ${keyPair.publicKey.substring(0, 50)}...';
|
|
});
|
|
} catch (e) {
|
|
print("_generateRsaKeyPair error: $e");
|
|
setState(() => _statusMessage = 'Error: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> _encryptPrivateKey() async
|
|
{
|
|
if (_keyPair == null) {
|
|
setState(() => _statusMessage = 'Please generate RSA key pair first!');
|
|
return;
|
|
}
|
|
|
|
const password = 'user_password_123';
|
|
setState(() => _statusMessage = 'Encrypting private key with password...');
|
|
try {
|
|
final encrypted = await _sdk.encryptPrivateKey(
|
|
privateKey: _keyPair!.privateKey,
|
|
password: password,
|
|
);
|
|
setState(() {
|
|
_encryptedPrivateKey = encrypted;
|
|
_statusMessage = 'Private key encrypted successfully!';
|
|
});
|
|
} catch (e) {
|
|
setState(() => _statusMessage = 'Error: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> _decryptPrivateKey() async
|
|
{
|
|
if (_encryptedPrivateKey == null) {
|
|
setState(() => _statusMessage = 'No encrypted private key to decrypt!');
|
|
return;
|
|
}
|
|
|
|
const password = 'user_password_123';
|
|
setState(() => _statusMessage = 'Decrypting private key...');
|
|
try {
|
|
final decrypted = await _sdk.decryptPrivateKey(
|
|
encryptedPrivateKey: _encryptedPrivateKey!,
|
|
password: password,
|
|
);
|
|
setState(() {
|
|
_statusMessage = 'Private key decrypted successfully!\n$decrypted';
|
|
});
|
|
} catch (e) {
|
|
setState(() => _statusMessage = 'Error: $e');
|
|
}
|
|
}
|
|
|
|
// ==================== 會話金鑰管理 ====================
|
|
|
|
Future<void> _generateSessionKey() async
|
|
{
|
|
setState(() => _statusMessage = 'Generating session key...');
|
|
try {
|
|
final sessionKey = await _sdk.generateSessionKey(initialRound: 1);
|
|
setState(() {
|
|
_sessionKey = sessionKey;
|
|
_statusMessage = 'Session key generated!\nKey: ${sessionKey.key}\nRound: ${sessionKey.round}';
|
|
});
|
|
} catch (e) {
|
|
setState(() => _statusMessage = 'Error: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> _encryptSessionKey() async
|
|
{
|
|
if (_sessionKey == null || _keyPair == null) {
|
|
setState(() => _statusMessage = 'Please generate session key and RSA key pair first!');
|
|
return;
|
|
}
|
|
|
|
setState(() => _statusMessage = 'Encrypting session key with RSA public key...');
|
|
|
|
try {
|
|
final encrypted = await _sdk.encryptSessionKey(
|
|
sessionKey: _sessionKey!.key,
|
|
publicKey: _keyPair!.publicKey,
|
|
);
|
|
setState(() {
|
|
_statusMessage = 'Session key encrypted successfully!\n$encrypted';
|
|
});
|
|
} catch (e) {
|
|
setState(() => _statusMessage = 'Error: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> _decryptSessionKey() async
|
|
{
|
|
if (_keyPair == null) {
|
|
setState(() => _statusMessage = 'Please generate RSA key pair first!');
|
|
return;
|
|
}
|
|
|
|
// 這裡應該使用之前加密的會話金鑰
|
|
if (_sessionKey == null) {
|
|
setState(() => _statusMessage = 'Please generate session key first!');
|
|
return;
|
|
}
|
|
|
|
setState(() => _statusMessage = 'Decrypting session key...');
|
|
try {
|
|
// 先加密再解密測試
|
|
final encrypted = await _sdk.encryptSessionKey(
|
|
sessionKey: _sessionKey!.key,
|
|
publicKey: _keyPair!.publicKey,
|
|
);
|
|
final decrypted = await _sdk.decryptSessionKey(
|
|
encryptedSessionKey: encrypted,
|
|
privateKey: _keyPair!.privateKey,
|
|
);
|
|
setState(() {
|
|
_statusMessage = 'Session key decrypted successfully!\nOriginal: ${_sessionKey!.key}\nDecrypted: $decrypted';
|
|
});
|
|
} catch (e) {
|
|
setState(() => _statusMessage = 'Error: $e');
|
|
}
|
|
}
|
|
|
|
// ==================== 訊息加解密 ====================
|
|
|
|
Future<void> _encryptMessage() async
|
|
{
|
|
if (_sessionKey == null) {
|
|
setState(() => _statusMessage = 'Please generate session key first!');
|
|
return;
|
|
}
|
|
|
|
const plaintext = 'Hello, this is a secret message!';
|
|
setState(() => _statusMessage = 'Encrypting message...');
|
|
try {
|
|
final encrypted = await _sdk.encryptMessage(
|
|
plaintext: plaintext,
|
|
sessionKey: _sessionKey!.key,
|
|
round: _sessionKey!.round,
|
|
);
|
|
setState(() {
|
|
_encryptedMessage = encrypted;
|
|
_statusMessage = 'Message encrypted!\nRound: ${encrypted.round}\nData: ${encrypted.data}';
|
|
});
|
|
} catch (e) {
|
|
setState(() => _statusMessage = 'Error: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> _decryptMessage() async
|
|
{
|
|
if (_encryptedMessage == null || _sessionKey == null) {
|
|
setState(() => _statusMessage = 'No encrypted message to decrypt!');
|
|
return;
|
|
}
|
|
|
|
setState(() => _statusMessage = 'Decrypting message...');
|
|
try {
|
|
final decrypted = await _sdk.decryptMessage(
|
|
encryptedData: _encryptedMessage!.data,
|
|
sessionKey: _sessionKey!.key,
|
|
round: _encryptedMessage!.round,
|
|
);
|
|
setState(() {
|
|
_decryptedMessage = decrypted;
|
|
_statusMessage = 'Message decrypted: $decrypted';
|
|
});
|
|
} catch (e) {
|
|
setState(() => _statusMessage = 'Error: $e');
|
|
}
|
|
}
|
|
|
|
// ==================== 原生平台同步 ====================
|
|
|
|
Future<void> _syncEncryptionKeys() async
|
|
{
|
|
if (_sessionKey == null) {
|
|
setState(() => _statusMessage = 'Please generate session key first!');
|
|
return;
|
|
}
|
|
|
|
setState(() => _statusMessage = 'Syncing encryption keys to native...');
|
|
try {
|
|
await _sdk.syncEncryptionKey(
|
|
chatId: 'test_chat_123',
|
|
activeRound: _sessionKey!.round,
|
|
round: _sessionKey!.round,
|
|
activeKey: _sessionKey!.key,
|
|
isSingle: false,
|
|
);
|
|
setState(() => _statusMessage = 'Encryption keys synced to native platform!');
|
|
} catch (e) {
|
|
setState(() => _statusMessage = 'Error: $e');
|
|
}
|
|
}
|
|
|
|
// ==================== 推送通知解密 ====================
|
|
|
|
Future<void> _setupAesSecret() async
|
|
{
|
|
// 設置 release.json 中的 AES_SECRET
|
|
const aesSecret = '468171c825c02408cc99935447c785a5';
|
|
setState(() => _statusMessage = 'Setting AES_SECRET...');
|
|
try {
|
|
await _sdk.setAesSecret(aesSecret: aesSecret);
|
|
setState(() => _statusMessage = 'AES_SECRET set successfully!');
|
|
} catch (e) {
|
|
setState(() => _statusMessage = 'Error: $e');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context)
|
|
{
|
|
return MaterialApp(
|
|
home: Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('CipherGuard SDK Example'),
|
|
),
|
|
body: SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Running on: $_platformVersion\n', style: Theme.of(context).textTheme.titleMedium),
|
|
|
|
const Text('=== RSA 金鑰管理 ===', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child:ElevatedButton(onPressed: _generateRsaKeyPair, child: const Text('生成 RSA 金鑰對',)
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
Expanded(child: ElevatedButton(onPressed: _keyPair != null ? _encryptPrivateKey : null, child: const Text('加密私鑰',style: TextStyle(fontSize: 10),))),
|
|
const SizedBox(width: 8),
|
|
Expanded(child: ElevatedButton(onPressed: _encryptedPrivateKey != null ? _decryptPrivateKey : null, child: const Text('解密私鑰',style: TextStyle(fontSize: 10),)),),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
const Text('=== 會話金鑰管理 ===', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: ElevatedButton(onPressed: _generateSessionKey, child: const Text('生成會話金鑰',style: TextStyle(fontSize: 10),)),
|
|
),
|
|
|
|
const SizedBox(width: 8),
|
|
|
|
Expanded(
|
|
child: ElevatedButton(
|
|
onPressed: (_sessionKey != null && _keyPair != null) ? _encryptSessionKey : null,
|
|
child: const Text('加密會話金鑰',style: TextStyle(fontSize: 10),)
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: ElevatedButton(
|
|
onPressed: (_keyPair != null && _sessionKey != null) ? _decryptSessionKey : null,
|
|
child: const Text('解密會話金鑰',style: TextStyle(fontSize: 10),)
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 8),
|
|
|
|
const Text('=== 訊息加解密 ===', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
Row(
|
|
children: [
|
|
ElevatedButton(
|
|
onPressed: _sessionKey != null ? _encryptMessage : null,
|
|
child: const Text('加密訊息')
|
|
),
|
|
const SizedBox(width: 8),
|
|
ElevatedButton(
|
|
onPressed: _encryptedMessage != null ? _decryptMessage : null,
|
|
child: const Text('解密訊息')
|
|
),
|
|
],
|
|
),
|
|
if (_decryptedMessage.isNotEmpty)
|
|
Text('解密結果: $_decryptedMessage', style: const TextStyle(color: Colors.green)),
|
|
const SizedBox(height: 8),
|
|
|
|
const Text('=== 原生平台同步 ===', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
ElevatedButton(
|
|
onPressed: _sessionKey != null ? _syncEncryptionKeys : null,
|
|
child: const Text('同步加密金鑰到原生')
|
|
),
|
|
const SizedBox(height: 8),
|
|
|
|
const Text('=== 推送通知解密 ===', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
ElevatedButton(onPressed: _setupAesSecret, child: const Text('設置 AES_SECRET')),
|
|
const SizedBox(height: 16),
|
|
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
color: Colors.grey[200],
|
|
width: double.infinity,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text('狀態:', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
Text(_statusMessage),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|