CSharpCryptoUtils 0.0.3

dotnet add package CSharpCryptoUtils --version 0.0.3
                    
NuGet\Install-Package CSharpCryptoUtils -Version 0.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CSharpCryptoUtils" Version="0.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CSharpCryptoUtils" Version="0.0.3" />
                    
Directory.Packages.props
<PackageReference Include="CSharpCryptoUtils" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CSharpCryptoUtils --version 0.0.3
                    
#r "nuget: CSharpCryptoUtils, 0.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CSharpCryptoUtils@0.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CSharpCryptoUtils&version=0.0.3
                    
Install as a Cake Addin
#tool nuget:?package=CSharpCryptoUtils&version=0.0.3
                    
Install as a Cake Tool

CSharpCryptoUtils

一个为区块链和金融科技应用提供加密工具的 C# 库,包括加密、哈希和密钥管理功能。

特性

  • 🔐 基于 ECDSA P-521 曲线的密钥生成
  • ✍️ 数字签名与验证(SHA-512 哈希算法)
  • 🔄 密钥导入/导出(支持 JWK 和 Hex 格式)
  • 🌐 跨平台兼容(与 Web Crypto API、TypeScript、Flutter 等平台互操作)
  • 📦 支持 .NET 7.0, 8.0, 9.0

安装

NuGet Package Manager

dotnet add package CSharpCryptoUtils

或在 Visual Studio 的包管理器控制台中:

Install-Package CSharpCryptoUtils

快速开始

1. 生成密钥对

using CSharpCryptoUtils;

// 生成新的 ECDSA P-521 密钥对
var keyPair = await KeyGenerator.GenerateKeyPairAsync();

Console.WriteLine("密钥对生成成功!");

2. 数字签名

// 对数据进行签名
string testData = "Hello, World!";
string signature = await keyPair.PrivateKey.SignAsync(testData);

Console.WriteLine($"签名: {signature}");

3. 验证签名

// 验证签名
bool isValid = await keyPair.PublicKey.VerifyAsync(signature, testData);

if (isValid)
{
    Console.WriteLine("✓ 签名验证成功");
}
else
{
    Console.WriteLine("✗ 签名验证失败");
}

详细使用指南

密钥管理

导出私钥(JWK 格式)
// 导出私钥为 JSON Web Key (JWK) 格式
string jwkString = await keyPair.PrivateKey.ExportKeyAsJWKStringAsync();

// JWK 示例:
// {
//   "kty": "EC",
//   "crv": "P-521",
//   "d": "base64url_encoded_private_key",
//   "x": "base64url_encoded_x_coordinate",
//   "y": "base64url_encoded_y_coordinate",
//   "ext": true
// }

Console.WriteLine($"私钥 (JWK): {jwkString}");

// 保存到文件
await File.WriteAllTextAsync("private-key.json", jwkString);
导入私钥(从 JWK)
// 从文件读取
string jwkString = await File.ReadAllTextAsync("private-key.json");

// 导入私钥
var privateKey = await PrivateKey.FromJWKStringAsync(jwkString);

// 使用导入的私钥进行签名
string signature = await privateKey.SignAsync("Test message");
导出公钥(十六进制格式)
// 导出公钥为十六进制字符串
// 格式: X坐标(66字节) + Y坐标(66字节) = 132字节 = 264个十六进制字符
string hexString = await keyPair.PublicKey.ExportKeyAsHexStringAsync();

Console.WriteLine($"公钥长度: {hexString.Length} 个字符"); // 264
Console.WriteLine($"公钥 (Hex): {hexString}");

// 保存到文件
await File.WriteAllTextAsync("public-key.hex", hexString);
导入公钥(从十六进制)
// 从文件读取
string hexString = await File.ReadAllTextAsync("public-key.hex");

// 导入公钥
var publicKey = await PublicKey.FromHexStringAsync(hexString);

// 使用导入的公钥验证签名
bool isValid = await publicKey.VerifyAsync(signature, "Test message");

完整示例

示例 1:密钥生成、签名与验证

using CSharpCryptoUtils;

public class CryptoExample
{
    public static async Task Main()
    {
        // 1. 生成密钥对
        var keyPair = await KeyGenerator.GenerateKeyPairAsync();
        Console.WriteLine("✓ 密钥对生成成功");

        // 2. 导出并保存密钥
        var privateKeyJwk = await keyPair.PrivateKey.ExportKeyAsJWKStringAsync();
        var publicKeyHex = await keyPair.PublicKey.ExportKeyAsHexStringAsync();
        
        await File.WriteAllTextAsync("private.json", privateKeyJwk);
        await File.WriteAllTextAsync("public.hex", publicKeyHex);
        Console.WriteLine("✓ 密钥已保存");

        // 3. 签名数据
        string message = "Important transaction data";
        string signature = await keyPair.PrivateKey.SignAsync(message);
        Console.WriteLine($"✓ 签名: {signature.Substring(0, 32)}...");

        // 4. 验证签名
        bool isValid = await keyPair.PublicKey.VerifyAsync(signature, message);
        Console.WriteLine($"✓ 签名验证: {(isValid ? "成功" : "失败")}");

        // 5. 使用错误的数据验证(应该失败)
        bool isInvalid = await keyPair.PublicKey.VerifyAsync(signature, "Wrong data");
        Console.WriteLine($"✓ 错误数据验证: {(isInvalid ? "成功" : "失败")} (预期失败)");
    }
}

示例 2:密钥持久化与恢复

using CSharpCryptoUtils;

public class KeyPersistenceExample
{
    // 保存密钥对
    public static async Task SaveKeyPair(KeyPair keyPair, string directory)
    {
        Directory.CreateDirectory(directory);
        
        var privateKeyJwk = await keyPair.PrivateKey.ExportKeyAsJWKStringAsync();
        var publicKeyHex = await keyPair.PublicKey.ExportKeyAsHexStringAsync();
        
        await File.WriteAllTextAsync(Path.Combine(directory, "private.json"), privateKeyJwk);
        await File.WriteAllTextAsync(Path.Combine(directory, "public.hex"), publicKeyHex);
    }

    // 加载密钥对
    public static async Task<(PrivateKey, PublicKey)> LoadKeyPair(string directory)
    {
        var privateKeyJwk = await File.ReadAllTextAsync(Path.Combine(directory, "private.json"));
        var publicKeyHex = await File.ReadAllTextAsync(Path.Combine(directory, "public.hex"));
        
        var privateKey = await PrivateKey.FromJWKStringAsync(privateKeyJwk);
        var publicKey = await PublicKey.FromHexStringAsync(publicKeyHex);
        
        return (privateKey, publicKey);
    }

    public static async Task Main()
    {
        // 生成并保存
        var keyPair = await KeyGenerator.GenerateKeyPairAsync();
        await SaveKeyPair(keyPair, "./keys");
        Console.WriteLine("✓ 密钥已保存到 ./keys 目录");

        // 加载并使用
        var (privateKey, publicKey) = await LoadKeyPair("./keys");
        
        string message = "Test message";
        string signature = await privateKey.SignAsync(message);
        bool isValid = await publicKey.VerifyAsync(signature, message);
        
        Console.WriteLine($"✓ 密钥恢复成功,签名验证: {(isValid ? "通过" : "失败")}");
    }
}

示例 3:跨平台密钥共享

using CSharpCryptoUtils;
using System.Text.Json;

public class CrossPlatformExample
{
    public static async Task Main()
    {
        // 生成密钥对
        var keyPair = await KeyGenerator.GenerateKeyPairAsync();

        // 导出为 JWK(可以与 JavaScript/TypeScript 共享)
        var privateKeyJwk = await keyPair.PrivateKey.ExportKeyAsJWKStringAsync();
        var publicKeyHex = await keyPair.PublicKey.ExportKeyAsHexStringAsync();

        Console.WriteLine("=== 私钥 (JWK - 用于 JavaScript/TypeScript) ===");
        Console.WriteLine(JsonSerializer.Serialize(
            JsonSerializer.Deserialize<object>(privateKeyJwk),
            new JsonSerializerOptions { WriteIndented = true }
        ));

        Console.WriteLine("\n=== 公钥 (Hex - 用于各种平台) ===");
        Console.WriteLine(publicKeyHex);

        // 在 C# 中签名
        string message = "Cross-platform message";
        string signature = await keyPair.PrivateKey.SignAsync(message);
        Console.WriteLine($"\n=== 签名 (Hex) ===");
        Console.WriteLine(signature);

        // 这个签名可以在其他平台使用相同的公钥进行验证
        // 例如在 JavaScript 中:
        // const publicKey = await crypto.subtle.importKey("jwk", jwkPublicKey, ...);
        // const isValid = await crypto.subtle.verify(..., publicKey, signatureBytes, dataBytes);
    }
}

算法规格

加密算法

  • 算法: ECDSA (Elliptic Curve Digital Signature Algorithm)
  • 曲线: P-521 (secp521r1 / nistP521)
  • 哈希: SHA-512
  • 签名格式: IEEE P1363 (Raw format - R||S concatenation)

密钥格式

私钥 (JWK)
{
  "kty": "EC",
  "crv": "P-521",
  "d": "<base64url-encoded-private-key>",
  "x": "<base64url-encoded-x-coordinate>",
  "y": "<base64url-encoded-y-coordinate>",
  "ext": true
}
公钥 (Hex)
<x-coordinate-132-hex-chars><y-coordinate-132-hex-chars>

总长度:264 个十六进制字符(132 字节)

跨平台兼容性

此库设计为与以下平台兼容:

  • JavaScript/TypeScript: Web Crypto API
  • Flutter/Dart: pointycastle 库
  • Node.js: crypto 模块
  • 其他 C# 应用: 本库

与 JavaScript 互操作示例

JavaScript 端签名
// JavaScript 端生成密钥对并签名
async function signInJavaScript() {
    // 生成密钥对
    const keyPair = await crypto.subtle.generateKey(
        {
            name: "ECDSA",
            namedCurve: "P-521"
        },
        true,
        ["sign", "verify"]
    );
    
    // 导出私钥为 JWK
    const privateKeyJwk = await crypto.subtle.exportKey("jwk", keyPair.privateKey);
    
    // 导出公钥为 raw 格式
    const publicKeyRaw = await crypto.subtle.exportKey("raw", keyPair.publicKey);
    const publicKeyHex = Array.from(new Uint8Array(publicKeyRaw))
        .map(b => b.toString(16).padStart(2, '0'))
        .join('');
    
    // 对消息进行签名
    const message = "Cross-platform message";
    const messageBytes = new TextEncoder().encode(message);
    const signatureBytes = await crypto.subtle.sign(
        {
            name: "ECDSA",
            hash: "SHA-512"
        },
        keyPair.privateKey,
        messageBytes
    );
    
    // 转换签名为十六进制
    const signature = Array.from(new Uint8Array(signatureBytes))
        .map(b => b.toString(16).padStart(2, '0'))
        .join('');
    
    return {
        privateKeyJwk,
        publicKeyHex: publicKeyHex.substring(2), // 去掉 0x04 前缀
        signature,
        message
    };
}
C# 端验证签名
using CSharpCryptoUtils;

public class JavaScriptInteropExample
{
    public static async Task Main()
    {
        // 从 JavaScript 接收的数据
        string publicKeyHex = "..."; // JavaScript 导出的公钥(264个十六进制字符)
        string signature = "...";    // JavaScript 生成的签名
        string message = "Cross-platform message";
        
        // 导入公钥
        var publicKey = await PublicKey.FromHexStringAsync(publicKeyHex);
        
        // 验证签名
        bool isValid = await publicKey.VerifyAsync(signature, message);
        
        if (isValid)
        {
            Console.WriteLine("✓ JavaScript 签名验证成功!");
        }
        else
        {
            Console.WriteLine("✗ JavaScript 签名验证失败!");
        }
    }
}
完整的跨平台工作流程
// 1. JavaScript 端:生成密钥并签名
const { publicKeyHex, signature, message } = await signInJavaScript();

// 2. 发送给 C# 后端
const response = await fetch('/api/verify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        publicKey: publicKeyHex,
        signature: signature,
        message: message
    })
});

const result = await response.json();
console.log('验证结果:', result.isValid); // true
// 3. C# 后端:API 端点接收并验证
[ApiController]
[Route("api")]
public class VerifyController : ControllerBase
{
    [HttpPost("verify")]
    public async Task<IActionResult> VerifySignature([FromBody] VerifyRequest request)
    {
        try
        {
            // 导入 JavaScript 生成的公钥
            var publicKey = await PublicKey.FromHexStringAsync(request.PublicKey);
            
            // 验证 JavaScript 生成的签名
            bool isValid = await publicKey.VerifyAsync(request.Signature, request.Message);
            
            return Ok(new { isValid });
        }
        catch (Exception ex)
        {
            return BadRequest(new { error = ex.Message });
        }
    }
}

public record VerifyRequest(string PublicKey, string Signature, string Message);

API 参考

KeyGenerator

方法 返回值 描述
GenerateKeyPairAsync() Task<KeyPair> 生成新的 ECDSA P-521 密钥对

PrivateKey

方法 参数 返回值 描述
SignAsync(string) data: 要签名的数据 Task<string> 对数据进行签名,返回十六进制签名
ExportKeyAsJWKStringAsync() - Task<string> 导出为 JWK JSON 字符串
FromJWKStringAsync(string) jwkString: JWK 字符串 Task<PrivateKey> 从 JWK 导入私钥

PublicKey

方法 参数 返回值 描述
VerifyAsync(string, string) signature: 签名<br>data: 原始数据 Task<bool> 验证签名是否有效
ExportKeyAsHexStringAsync() - Task<string> 导出为十六进制字符串
FromHexStringAsync(string) hexString: 十六进制字符串 Task<PublicKey> 从十六进制导入公钥

最佳实践

安全性

  1. 私钥保护

    // ❌ 不要将私钥硬编码在代码中
    const string privateKey = "...";
    
    // ✅ 从安全的配置或密钥管理服务读取
    var privateKeyJwk = await keyVault.GetSecretAsync("private-key");
    var privateKey = await PrivateKey.FromJWKStringAsync(privateKeyJwk);
    
  2. 密钥存储

    // ✅ 使用操作系统的密钥存储
    // Windows: DPAPI
    // Linux/macOS: Keychain
    
    // 或使用专门的密钥管理服务
    // - Azure Key Vault
    // - AWS KMS
    // - HashiCorp Vault
    
  3. 资源释放

    // ✅ 使用完毕后释放密钥对象
    using var privateKey = await PrivateKey.FromJWKStringAsync(jwk);
    // ... 使用 privateKey
    // 自动释放
    

性能优化

  1. 重用密钥对象

    // ✅ 在应用程序生命周期中重用密钥对象
    public class SignatureService
    {
        private readonly PrivateKey _privateKey;
    
        public SignatureService(string jwk)
        {
            _privateKey = PrivateKey.FromJWKStringAsync(jwk).Result;
        }
    
        public Task<string> SignAsync(string data)
        {
            return _privateKey.SignAsync(data);
        }
    }
    
  2. 批量操作

    // ✅ 批量签名多个消息
    var messages = new[] { "msg1", "msg2", "msg3" };
    var signatures = await Task.WhenAll(
        messages.Select(msg => privateKey.SignAsync(msg))
    );
    

故障排除

常见错误

  1. "Invalid hex string length"

    • 原因:公钥十六进制字符串长度不是 264 个字符
    • 解决:确保公钥格式正确(132 字节 = 264 hex chars)
  2. "Invalid JWK: expected EC P-521 key"

    • 原因:JWK 不是 P-521 曲线的 EC 密钥
    • 解决:检查 JWK 的 crv 字段是否为 "P-521"
  3. 签名验证失败

    • 原因:数据、签名或公钥不匹配
    • 解决:确保签名和验证使用相同的数据,公钥与私钥匹配

调试技巧

// 启用详细日志
try
{
    var keyPair = await KeyGenerator.GenerateKeyPairAsync();
    var signature = await keyPair.PrivateKey.SignAsync(data);
    var isValid = await keyPair.PublicKey.VerifyAsync(signature, data);
}
catch (CryptographicException ex)
{
    Console.WriteLine($"加密操作失败: {ex.Message}");
    Console.WriteLine($"堆栈跟踪: {ex.StackTrace}");
}

测试覆盖:

  • ✅ 密钥生成
  • ✅ 签名与验证
  • ✅ 密钥导入/导出
  • ✅ 跨平台兼容性
  • ✅ 错误处理

依赖项

  • .NET 7.0+ (System.Security.Cryptography)
  • System.Text.Json (用于 JWK 序列化)

版本历史

1.0.0 (2025-01-04)

  • ✨ 初始发布
  • 🔐 支持 ECDSA P-521 密钥生成
  • ✍️ 数字签名与验证
  • 🔄 JWK 和 Hex 格式的密钥导入/导出
  • 🌐 跨平台兼容性

许可证

MIT License - 详见 LICENSE 文件


ExWallets Team © 2025

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.3 480 11/20/2025
0.0.2 432 11/20/2025