Blazor客户端(.NET 6无服务端)非对称加密实现方案咨询
Blazor WebAssembly 客户端非对称加密实现方案(.NET 6)
方案一:调用浏览器Web Crypto API(推荐)
浏览器原生支持Web Crypto API,Blazor WASM可通过JS互操作直接调用,完全避开.NET加密库的兼容性问题,是最稳定的实现方式。
核心实现步骤
- 生成RSA密钥对:调用
crypto.subtle.generateKey生成RSA-OAEP密钥对,可导出SPKI格式公钥和PKCS#8格式私钥用于存储/传输。 - 加密:将明文转为ArrayBuffer,用公钥调用
crypto.subtle.encrypt完成加密。 - 解密:将密文转为ArrayBuffer,用私钥调用
crypto.subtle.decrypt完成解密。
代码示例
- 新建
CryptoUtils.js文件,添加JS工具函数:
window.cryptoUtils = { generateRsaKeyPair: async function () { const keyPair = await window.crypto.subtle.generateKey( { name: "RSA-OAEP", modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: "SHA-256" }, true, ["encrypt", "decrypt"] ); const publicKey = await window.crypto.subtle.exportKey("spki", keyPair.publicKey); const privateKey = await window.crypto.subtle.exportKey("pkcs8", keyPair.privateKey); return { publicKey: arrayBufferToBase64(publicKey), privateKey: arrayBufferToBase64(privateKey) }; }, encryptWithPublicKey: async function (publicKeyBase64, plainText) { const publicKey = await window.crypto.subtle.importKey( "spki", base64ToArrayBuffer(publicKeyBase64), { name: "RSA-OAEP", hash: "SHA-256" }, false, ["encrypt"] ); const encoder = new TextEncoder(); const data = encoder.encode(plainText); const encrypted = await window.crypto.subtle.encrypt({ name: "RSA-OAEP" }, publicKey, data); return arrayBufferToBase64(encrypted); }, decryptWithPrivateKey: async function (privateKeyBase64, encryptedText) { const privateKey = await window.crypto.subtle.importKey( "pkcs8", base64ToArrayBuffer(privateKeyBase64), { name: "RSA-OAEP", hash: "SHA-256" }, false, ["decrypt"] ); const encryptedData = base64ToArrayBuffer(encryptedText); const decrypted = await window.crypto.subtle.decrypt({ name: "RSA-OAEP" }, privateKey, encryptedData); const decoder = new TextDecoder(); return decoder.decode(decrypted); } }; function arrayBufferToBase64(buffer) { return btoa(String.fromCharCode(...new Uint8Array(buffer))); } function base64ToArrayBuffer(base64) { const binaryString = atob(base64); const bytes = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes.buffer; }
- Blazor组件中通过
IJSRuntime调用:
@inject IJSRuntime JsRuntime <button @onclick="GenerateKeys">生成RSA密钥对</button> <button @onclick="TestEncryptDecrypt">测试加解密</button> @code { private string? _publicKey; private string? _privateKey; private string? _encryptedText; private string? _decryptedText; private async Task GenerateKeys() { var keyPair = await JsRuntime.InvokeAsync<KeyPair>("window.cryptoUtils.generateRsaKeyPair"); _publicKey = keyPair.PublicKey; _privateKey = keyPair.PrivateKey; } private async Task TestEncryptDecrypt() { const string plainText = "测试非对称加密内容"; _encryptedText = await JsRuntime.InvokeAsync<string>( "window.cryptoUtils.encryptWithPublicKey", _publicKey, plainText); _decryptedText = await JsRuntime.InvokeAsync<string>( "window.cryptoUtils.decryptWithPrivateKey", _privateKey, _encryptedText); } public class KeyPair { public string PublicKey { get; set; } = string.Empty; public string PrivateKey { get; set; } = string.Empty; } }
方案二:使用Blazor.WebCrypto NuGet包
该包封装了Web Crypto API的.NET调用,无需手写JS互操作,适配.NET 6+。
核心操作
- 安装包:
Install-Package Blazor.WebCrypto - 生成密钥对:通过
CryptoService.GenerateKeyAsync生成RSA密钥对。 - 加解密:调用
CryptoService.EncryptAsync和CryptoService.DecryptAsync方法。
代码示例
@inject Blazor.WebCrypto.ICryptoService CryptoService <button @onclick="GenerateAndTest">生成密钥并测试</button> @code { private async Task GenerateAndTest() { // 生成RSA-OAEP密钥对 var keyPair = await CryptoService.GenerateKeyAsync( new RsaHashedKeyGenParams { Name = KeyAlgorithm.RsaOaep, ModulusLength = 2048, PublicExponent = new byte[] { 0x01, 0x00, 0x01 }, Hash = HashAlgorithm.Sha256 }, extractable: true, usages: new[] { KeyUsage.Encrypt, KeyUsage.Decrypt }); // 加密 var plainText = "测试内容"; var encoder = new TextEncoder(); var plainData = encoder.Encode(plainText); var encryptedData = await CryptoService.EncryptAsync( new RsaOaepParams { Name = KeyAlgorithm.RsaOaep }, keyPair.PublicKey, plainData); // 解密 var decryptedData = await CryptoService.DecryptAsync( new RsaOaepParams { Name = KeyAlgorithm.RsaOaep }, keyPair.PrivateKey, encryptedData); var decoder = new TextDecoder(); var decryptedText = decoder.Decode(decryptedData); } }
方案三:使用BouncyCastle WASM适配版
BouncyCastle提供了专门的WASM包BouncyCastle.Crypto.Wasm,可直接在Blazor WASM中使用RSA等加密算法,无需依赖浏览器API。
核心步骤
- 安装包:
Install-Package BouncyCastle.Crypto.Wasm - 生成密钥对:用
RsaKeyPairGenerator生成密钥,导出PEM格式公私钥。 - 加解密:配合
OaepEncoding实现RSA-OAEP加解密。
代码示例
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities.Encoders; // 生成RSA密钥对 var generator = new RsaKeyPairGenerator(); generator.Init(new KeyGenerationParameters(new SecureRandom(), 2048)); var keyPair = generator.GenerateKeyPair(); // 导出公钥(PEM格式) var publicKeyParams = (RsaKeyParameters)keyPair.Public; var publicKeyPem = PublicKeyFactory.CreateSubjectPublicKeyInfo(publicKeyParams).GetDerEncoded(); var publicKeyBase64 = Convert.ToBase64String(publicKeyPem); // 导出私钥(PEM格式) var privateKeyParams = (RsaPrivateCrtKeyParameters)keyPair.Private; var privateKeyPem = PrivateKeyFactory.CreatePrivateKeyInfo(privateKeyParams).GetDerEncoded(); var privateKeyBase64 = Convert.ToBase64String(privateKeyPem); // 加密 var encryptEngine = new OaepEncoding(new RsaEngine(), new Sha256Digest()); encryptEngine.Init(true, publicKeyParams); var plainBytes = System.Text.Encoding.UTF8.GetBytes("测试内容"); var encryptedBytes = encryptEngine.ProcessBlock(plainBytes, 0, plainBytes.Length); var encryptedBase64 = Convert.ToBase64String(encryptedBytes); // 解密 var decryptEngine = new OaepEncoding(new RsaEngine(), new Sha256Digest()); decryptEngine.Init(false, privateKeyParams); var encryptedBytesFromBase64 = Convert.FromBase64String(encryptedBase64); var decryptedBytes = decryptEngine.ProcessBlock(encryptedBytesFromBase64, 0, encryptedBytesFromBase64.Length); var decryptedText = System.Text.Encoding.UTF8.GetString(decryptedBytes);
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

