NdsForge.NET 1.0.1
Read, validate, edit, compare, and build Nintendo DS and DSi images from .NET
Loading...
Searching...
No Matches
NdsDsiRsaSignatureProvider.cs
1using System.Security.Cryptography;
2
3namespace NdsForge;
4
9public sealed class NdsDsiRsaSignatureProvider : INdsDsiSignatureProvider, IDisposable
10{
12 private RSAParameters _parameters;
14 private bool _disposed;
15
19 {
20 ArgumentNullException.ThrowIfNull(rsa);
21 if (rsa.KeySize != 1024)
22 {
23 throw new ArgumentException("DSi header signatures require a 1024-bit RSA key.", nameof(rsa));
24 }
25
26 _parameters = rsa.ExportParameters(includePrivateParameters: true);
27 if (_parameters.D is null)
28 {
29 throw new ArgumentException("The RSA object does not expose a private signing key.", nameof(rsa));
30 }
31 }
32
34 public void SignHeader(ReadOnlySpan<byte> signedHeader, Span<byte> destination)
35 {
36 ObjectDisposedException.ThrowIf(_disposed, this);
37 if (signedHeader.Length != 0xE00 || destination.Length != 128)
38 {
39 throw new ArgumentException("DSi signing requires a 0xE00-byte header prefix and 128-byte destination.");
40 }
41
42 using RSA rsa = RSA.Create();
43 rsa.ImportParameters(_parameters);
44#pragma warning disable CA5350, CA5387 // The legacy DSi signature format fixes SHA-1 and PKCS#1 v1.5.
45 if (!rsa.TrySignData(signedHeader, destination, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1, out int written) ||
46 written != destination.Length)
47#pragma warning restore CA5350, CA5387
48 {
49 throw new CryptographicException("The RSA provider did not produce the required 128-byte DSi signature.");
50 }
51 }
52
54 public void Dispose()
55 {
56 if (_disposed)
57 {
58 return;
59 }
60
61 Clear(_parameters.D);
62 Clear(_parameters.DP);
63 Clear(_parameters.DQ);
64 Clear(_parameters.Exponent);
65 Clear(_parameters.InverseQ);
66 Clear(_parameters.Modulus);
67 Clear(_parameters.P);
68 Clear(_parameters.Q);
69 _parameters = default;
70 _disposed = true;
71 }
72
75 private static void Clear(byte[]? value)
76 {
77 if (value is not null)
78 {
79 CryptographicOperations.ZeroMemory(value);
80 }
81 }
82}
void Dispose()
Clears all copied private and public RSA components and permanently disables signing.
NdsDsiRsaSignatureProvider(RSA rsa)
Copies a complete DSi-sized private key rather than retaining the caller's cryptographic object.
void SignHeader(ReadOnlySpan< byte > signedHeader, Span< byte > destination)
Signs a finalized DSi header prefix into fixed signature-field storage.
Abstracts DSi header signing so build pipelines may use a managed private key, hardware-backed key,...