aardio 文档

BouncyCastle 扩展库 - 快速入门

参考链接: 🅰 aardio 文档 - .NET 调用指南 📄 BouncyCastle 文档增强检索

本文档 根据 BouncyCastle 用户手册 由 AI 自动翻译为 aardio 版 本,适用 aardio v40.7 以上版本,以及 aardio 扩展库 BouncyCastle v2.6.1 以上版本。

Bouncy Castle 介绍

开源组件 Bouncy Castle 是基于 .NET 的加密算法与协议实现库,不仅提供常用基础加密算法,还支持 CMS、OpenPGP、(D)TLS、TSP、X.509 证书生成等功能。此外,它还实现了美国国家标准与技术研究院(NIST)的后量子密码学标准化算法,如ML - DSA、ML - KEM、SLH - DSA、Falcon、经典McEliece、FrodoKEM、NTRU、NTRU Prime、Picnic、Saber 和 BIKE。

Bouncy Castle 仅需要系统自带的 NET .NET 4.6.1( Win10 1709 就已经自带,这基本是目前主流 .NET 程序的最低要求,即使更老的操作系统也都已普及安装了 )。

在 aardio 中使用 BouncyCastle 扩展库

aardio 提供了 BouncyCastle 扩展库,实际上这个扩展库的源代码只有几句代码,主要是添加了内存加载 BouncyCastle.Cryptography.dll 的代码,以实现生成无依赖的独立 EXE 文件。其他 BouncyCastle 的 .NET 接口在 aardio 里可以直接使用,不需要再额外封装。

1. 安装扩阿展库

✅ 在 aardio 中直接运行包含 import BouncyCastle 语句的代码也会自动安装扩展库。

2. 导入 BouncyCastle 名字空间

import BouncyCastle 语句会导入 .NET 的 BouncyCastle 名字空间。

要特别注意 aardio 的 import 语句与 C# 的 using 语句存在区别:

aardio 中访问 .NET 对象要写完整名字空间,示例:

import BouncyCastle; 
var sha3 = BouncyCastle.Crypto.Digests.Sha3Digest(256);

aardio 不能像 C# 那样用 Sha3Digest 代替 BouncyCastle.Crypto.Digests.Sha3Digest, 必须指定完整的名字空间。

但是在 aardio 里名字空间或者类都可以通过赋值语句指定更短的名称,例如:

//用局部变量指向名字空间
var Sha3Digest = BouncyCastle.Crypto.Digests.Sha3Digest;

//使用更短的名字直接访问对象
var sha3 = Sha3Digest(256);

注意在 aardio 中构造类的实例不需要使用 new 关键字。

随机数简介

在密码学领域,随机数至关重要。随机数有许多应用场景,例如为对称密码生成密钥、帮助为不对称算法生成大数(通常是素数),以及在加密算法中引入 nonce¹ 以防止(或减少)所谓的重放²攻击。

¹ nonce( Number once ) 是指定范围内的随机整数或伪随机整数。
² 重放攻击( Replay Attacks) 简单来说,就是当攻击者截获加密消息/数据并在稍后重新发送该消息/数据时发生的攻击。

当提到随机数时,至少有以下三种含义:

  1. TRNG(真随机数生成器)- 这些系统生成的数字(或比特串)来自物理随机源,如热/电压耗散噪声、放射性衰变噪声或大气噪声(参见 http://www.random.org)等许多随机物理过程。如果您的硬件支持 TRNG,则可以从 aardio 代码中访问它。

  2. PRNG(伪随机数生成器,也称为 DRBG,确定性随机比特生成器)- 这些是数学算法,通常使用称为种子值的整数初始化函数来生成数字。这些数字本质上不是真正的随机数,因为可以生成的此类值的数量是有限的 - 最终数字序列将重复。(与此形成对比的是像大气噪声 TRNG 这样的东西,它可以近似为连续的值集。因此,在实际应用中,使用 TRNG 我们可以生成无限数量的不同值。)

  3. CSPRNG(加密安全伪随机数生成器)- 这些同样使用数学算法生成随机比特串。PRNG 和 CSPRNG 之间的区别在于后者必须能够抵抗加密攻击。

在 Bouncy Castle .NET 加密程序集中,可以使用上述所有三种方式。.NET 直接支持线性同余算法的修改版本,可用作 PRNG。我们在下面的示例中使用它,因为我们希望在测试期间获得一致的密钥和密文。

aardio 提供了基于 PRNG 的 math.random(), 而生成随机字符串的 string.random() 函数同样基于 math.random() 生成的随机数。需要注意的是所有 aardio 线程启动时都会单独生成一个加密安全的随机数作为 math.random(), string.random() 函数的随机数种子,以避免多线程并发时默认可能生成相同的随机数序列的问题。也可以在运行时手动调用 math.randomize( seedNumber ) 重新设置 math.random() 的随机数种子。aardio 标准库的 crypt.random 则提供了基于系统熵源(System Entropy Source)的加密钱数随机数生成器(CSPRNG)。请参考:aardio 随机数与随机字符串

示例 - aardio 随机数

PRNG:


//设置固定的随机数种子
math.randomize(151) //除了测试目的,最好不要指定固定的随机数种子

//生成固定系列的伪随机数
for(i=1;10;1){
    print( math.random(1,0xFFFFFFFF) );
}

CSPRNG:

import crypt.random;

//创建随机数生成器
var rng = crypt.random();

//生成 5 个字节的随机 buffer
var buf = rng.buffer(5);

//生成 1 到 9 范围的随机整数
var n = rng.integer(1,9);

//生成 0 到 1 之间的随机小数
var num = rng.number();

示例 - C# 默认 PRNG

import BouncyCastle;
import console;

// 设置固定随机种子
var fixedRandomSeed = 151;
var fixedRandom = System.Random(fixedRandomSeed);

// 生成 32 字节随机数
var bytes = dotNet.buffer(32);
fixedRandom.NextBytes(bytes);

var number = raw.convert(bytes.Value,{INT num}).num;

console.log("固定种子随机数:", number);
console.pause();

上面的代码将为您提供一组一致的"随机"数字,用于测试。执行上述代码两次将生成相同的字节数组。

请注意,.NET 还在 System.Security.Cryptography.RandomNumberGenerator 类中提供了加密安全的 PRNG。BC API 也提供了 PRNG 和 CSPRNG,如下例所示。

示例 - BC 默认 SecureRandom

import BouncyCastle;
import console;

// 创建默认安全随机数生成器
var defaultSecureRandom = BouncyCastle.Security.SecureRandom();

// 生成32字节随机数
var bytes = dotNet.buffer(32);
defaultSecureRandom.NextBytes(bytes);

//安全随机数
console.hex(bytes.Value);
console.pause();

默认的 SecureRandom 基于 SHA256 摘要算法。种子值通过 .NET 内部类 System.Security.Cryptography.RandomNumberGenerator 提供。执行上述代码两次显示生成的字节集是不同的。如上例生成的 SecureRandom 在加密上是安全的,在大多数加密情况下已经足够。然而,BC API 还提供了几种 NIST SP.800-90A 推荐的方法来生成加密安全的随机数。

NIST 文档推荐基于以下内容的 DRBG:

下面的示例展示了基于 HMAC 的 SecureRandom 对象的生成。

示例 - BC HMAC SecureRandom

import BouncyCastle;
import console;

// 创建SHA256摘要
var digest = BouncyCastle.Crypto.Digests.Sha256Digest();

// 创建HMAC随机数生成器构建器
var hMacSecureRandomBuilder = BouncyCastle.Crypto.Prng.SP800SecureRandomBuilder(
    BouncyCastle.Security.SecureRandom(),
    false
);

// 设置个性化字符串
hMacSecureRandomBuilder.SetPersonalizationString(raw.buffer("aardio-app"));

// 创建HMAC摘要
var hmac = BouncyCastle.Crypto.Macs.HMac(digest);

// 构建随机数生成器
var hmacSecureRandom = hMacSecureRandomBuilder.BuildHMac(
    hmac, 
    null, // 不使用nonce
    false
);

// 生成 32 字节随机数
var bytes = dotNet.buffer(32);
hmacSecureRandom.NextBytes(bytes);

console.log("HMAC 安全随机数:", string.hex(bytes.Value));
console.pause();

Markdown 格式