Initial project
This commit is contained in:
377
packages/cipher_guard_sdk/example/lib/main.dart
Normal file
377
packages/cipher_guard_sdk/example/lib/main.dart
Normal file
@@ -0,0 +1,377 @@
|
||||
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),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user