Flutter加密通信插件flutter_curve25519的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter加密通信插件flutter_curve25519的使用

flutter_curve25519 是一个用于Flutter应用程序的插件,它实现了基于Curve25519椭圆曲线的加密功能。该插件支持Ed25519签名和X25519密钥交换协议,适用于安全通信场景。以下是关于如何使用flutter_curve25519插件的详细介绍和完整示例代码。

主要功能

  1. 生成密钥对:从给定的32字节随机种子生成公私钥对。
  2. 签名:使用私钥对消息进行签名,支持可选的随机化参数以生成非确定性签名。
  3. 验证签名:使用公钥验证消息的签名是否有效。
  4. 签名消息:将签名附加到消息末尾,返回已签名的消息。
  5. 打开签名消息:验证并提取已签名的消息,如果验证失败则返回null
  6. 共享密钥:通过X25519算法计算共享密钥,用于密钥协商。

详细说明

1. 生成密钥对
/// 从给定的32字节种子生成密钥对
final keypair = Curve25519KeyPair.fromSeed(Uint8List.fromList(seed));
  • seed:32字节的随机种子,建议使用安全的伪随机数生成器(CSPRNG)生成。
  • 返回值:包含privateKeypublicKey的密钥对对象。
2. 签名
/// 使用私钥对消息进行签名
final signature = Curve25519.sign(
    keypair.privateKey, message, Uint8List.fromList(optRandom));
  • privateKey:32字节的私钥。
  • message:待签名的消息,类型为Uint8List
  • optRandom:可选的64字节随机数据,用于生成非确定性签名。
  • 返回值:签名结果,类型为Uint8List
3. 验证签名
/// 使用公钥验证签名
var pass = Curve25519.verify(keypair.publicKey, message, signature);
  • publicKey:32字节的公钥。
  • message:原始消息,类型为Uint8List
  • signature:签名结果,类型为Uint8List
  • 返回值:1表示签名有效,0表示签名无效。
4. 签名消息
/// 签名并返回已签名的消息
final signedMessage = Curve25519.signMessage(
    keypair.privateKey, message, Uint8List.fromList(optRandom));
  • privateKey:32字节的私钥。
  • message:待签名的消息,类型为Uint8List
  • optRandom:可选的64字节随机数据,用于生成非确定性签名。
  • 返回值:已签名的消息,签名附加在消息末尾,类型为Uint8List
5. 打开签名消息
/// 验证并提取已签名的消息
final originalMessage = Curve25519.openMessage(keypair.publicKey, signedMessage);
  • publicKey:32字节的公钥。
  • signedMessage:已签名的消息,类型为Uint8List
  • 返回值:如果验证成功,返回原始消息;如果验证失败,返回null
6. 共享密钥
/// 计算共享密钥
final sharedKey = Curve25519.sharedKey(keypair.privateKey, peerPublicKey);
  • privateKey:32字节的私钥。
  • peerPublicKey:对端的32字节公钥。
  • 返回值:共享密钥,类型为Uint8List,长度为32字节。

完整示例代码

以下是一个完整的示例代码,展示了如何使用flutter_curve25519插件进行密钥生成、签名、验证和共享密钥计算。

import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';

import 'package:flutter_curve25519/flutter_curve25519.dart';

void main() {
  // 生成32字节的随机种子
  var seed = List.generate(32, (index) => Random().nextInt(256));

  // 从种子生成密钥对
  final keypair = Curve25519KeyPair.fromSeed(Uint8List.fromList(seed));
  print('生成的密钥对: $keypair');

  // 生成一条测试消息
  final message = base64Decode("BSHHNbsuQxc5vqIU/8C9zp4ziaF+kbyAqSzvc2b6zDUG");

  // 生成64字节的随机数据,用于非确定性签名
  var optRandom = List.generate(64, (index) => Random().nextInt(256));

  // 使用私钥对消息进行签名
  final signature = Curve25519.sign(
      keypair.privateKey, message, Uint8List.fromList(optRandom));
  print('生成的签名: ${base64Encode(signature)}');

  // 使用公钥验证签名
  var pass = Curve25519.verify(keypair.publicKey, message, signature);
  print('签名验证结果: $pass'); // 输出 1 表示签名有效

  // 签名并返回已签名的消息
  final signedMessage = Curve25519.signMessage(
      keypair.privateKey, message, Uint8List.fromList(optRandom));
  print('已签名的消息: ${base64Encode(signedMessage)}');

  // 验证并提取已签名的消息
  final originalMessage = Curve25519.openMessage(keypair.publicKey, signedMessage);
  if (originalMessage != null) {
    print('提取的原始消息: ${base64Encode(originalMessage)}');
  } else {
    print('签名验证失败');
  }

  // 模拟对端的公钥
  final peerPublicKey = keypair.publicKey;

  // 计算共享密钥
  final sharedKey = Curve25519.sharedKey(keypair.privateKey, peerPublicKey);
  print('计算的共享密钥: ${base64Encode(sharedKey)}');
}

运行结果

运行上述代码后,您将看到类似如下的输出:

生成的密钥对: {privateKey: [123, 45, ...], publicKey: [234, 56, ...]}
生成的签名: NrGeCn6ReYhGgFcD3KzBl/rpfk4lIpKxGkliuLWLQwU7vb7orbxUPJ9opqn1XS7ql31H6Tu2qwjqVmN12+gehA==
签名验证结果: 1
已签名的消息: BSHHNbsuQxc5vqIU/8C9zp4ziaF+kbyAqSzvc2b6zDUGNrGeCn6ReYhGgFcD3KzBl/rpfk4lIpKxGkliuLWLQwU7vb7orbxUPJ9opqn1XS7ql31H6Tu2qwjqVmN12+gehA==
提取的原始消息: BSHHNbsuQxc5vqIU/8C9zp4ziaF+kbyAqSzvc2b6zDUG
计算的共享密钥: Afehf5eexgV5if/bW2B3+RGJJDaE7sE6YiTABzzUHQwl

更多关于Flutter加密通信插件flutter_curve25519的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter加密通信插件flutter_curve25519的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,flutter_curve25519 是一个用于 Flutter 的加密通信插件,基于 Curve25519 椭圆曲线加密算法。Curve25519 是一种现代的、安全的加密算法,广泛用于密钥交换。下面是一个简单的示例,展示如何在 Flutter 应用中使用 flutter_curve25519 插件进行加密通信。

首先,确保你已经在 pubspec.yaml 文件中添加了 flutter_curve25519 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_curve25519: ^最新版本号

然后运行 flutter pub get 来获取依赖。

接下来是一个示例代码,展示如何使用 flutter_curve25519 进行密钥交换和加密通信:

import 'package:flutter/material.dart';
import 'package:flutter_curve25519/flutter_curve25519.dart';
import 'dart:typed_data';
import 'dart:convert';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Uint8List? privateKeyA;
  Uint8List? publicKeyA;
  Uint8List? privateKeyB;
  Uint8List? publicKeyB;
  Uint8List? sharedSecret;
  String? encryptedMessage;
  String? decryptedMessage;

  @override
  void initState() {
    super.initState();
    _generateKeys();
  }

  void _generateKeys() async {
    // 生成密钥对 A
    var keyPairA = await Curve25519.generateKeyPair();
    privateKeyA = keyPairA.privateKey;
    publicKeyA = keyPairA.publicKey;

    // 生成密钥对 B
    var keyPairB = await Curve25519.generateKeyPair();
    privateKeyB = keyPairB.privateKey;
    publicKeyB = keyPairB.publicKey;

    // 计算共享密钥
    sharedSecret = await Curve25519.calculateSharedSecret(privateKeyA!, publicKeyB!);

    setState(() {});
  }

  void _encryptMessage() {
    if (sharedSecret == null || privateKeyA == null || publicKeyB == null) return;

    String message = "Hello, this is a secret message!";
    Uint8List messageBytes = Uint8List.fromList(utf8.encode(message));
    Uint8List nonce = Uint8List.fromList(List.generate(12, (i) => i % 256)); // 12字节的随机nonce

    // 使用libsodium的加密方法(假设flutter_curve25519支持)
    // 注意:flutter_curve25519本身可能不提供完整的加密功能,这里仅为示例
    // 实际使用中可能需要结合其他库如pointycastle进行对称加密
    // Uint8List encrypted = await Curve25519.encrypt(messageBytes, nonce, sharedSecret!);

    // 由于flutter_curve25519可能不提供加密功能,这里我们模拟加密过程
    // 实际加密应使用对称加密算法如AES,结合sharedSecret作为密钥
    // 这里仅将messageBytes转换为Base64字符串作为模拟
    encryptedMessage = base64Encode(messageBytes);

    setState(() {});
  }

  void _decryptMessage() {
    if (sharedSecret == null || encryptedMessage == null) return;

    Uint8List encryptedBytes = Uint8List.fromList(base64Decode(encryptedMessage!));
    // Uint8List decrypted = await Curve25519.decrypt(encryptedBytes, nonce, sharedSecret!);

    // 由于flutter_curve25519可能不提供解密功能,这里我们模拟解密过程
    // 实际解密应使用与加密相同的对称加密算法和密钥
    // 这里直接将encryptedBytes转换回字符串(因为我们是模拟加密的)
    decryptedMessage = utf8.decode(encryptedBytes);

    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Curve25519 Example'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              if (privateKeyA != null && publicKeyA != null)
                Text('Private Key A: ${base64Encode(privateKeyA!)}'),
              if (publicKeyA != null)
                Text('Public Key A: ${base64Encode(publicKeyA!)}'),
              if (privateKeyB != null && publicKeyB != null)
                Text('Private Key B: ${base64Encode(privateKeyB!)}'),
              if (publicKeyB != null)
                Text('Public Key B: ${base64Encode(publicKeyB!)}'),
              if (sharedSecret != null)
                Text('Shared Secret: ${base64Encode(sharedSecret!)}'),
              ElevatedButton(
                onPressed: _encryptMessage,
                child: Text('Encrypt Message'),
              ),
              if (encryptedMessage != null)
                Text('Encrypted Message: $encryptedMessage'),
              ElevatedButton(
                onPressed: _decryptMessage,
                child: Text('Decrypt Message'),
              ),
              if (decryptedMessage != null)
                Text('Decrypted Message: $decryptedMessage'),
            ],
          ),
        ),
      ),
    );
  }
}

注意

  1. flutter_curve25519 插件本身可能不提供完整的加密和解密功能。上面的示例代码中加密和解密部分仅为示意,实际使用中需要结合其他库如 pointycastle 来实现对称加密。
  2. nonce 的生成应该是随机的,并且在使用中不应重复。在实际应用中,应该使用安全的随机数生成器来生成 nonce
  3. 示例代码中的 base64Encodebase64Decode 用于将二进制数据转换为字符串以便于显示,实际通信中应直接传输二进制数据。

确保你了解并遵循所有安全最佳实践,特别是在处理加密密钥和敏感数据时。

回到顶部