Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
RsaAlgorithm.cs
1using System;
2using System.Formats.Asn1;
3using System.Globalization;
4using System.Numerics;
5using System.Text;
10
12{
16 public abstract class RsaAlgorithm : SignatureAlgorithm
17 {
26 public override bool VerifySignature(byte[] Data, byte[] Signature, IPublicKey PublicKey,
27 ICommunicationLayer? Client)
28 {
29 if (PublicKey is not RsaPublicKey RsaParameters)
30 {
31 Client?.Error("No RSA public key provided or found.");
32 return false;
33 }
34
35 int Bits = (int)RsaParameters.Modulus.GetBitLength();
36
37 ASN1.ReportAlgorithmUse("RSA-PKCS-" + Bits.ToString(CultureInfo.InvariantCulture));
38
39 return this.VerifySignatureRsaPkcs1(Data, Signature,
40 RsaParameters.Modulus, RsaParameters.Exponent, Client);
41 }
42
52 public bool VerifySignatureRsaPkcs1(byte[] Data, byte[] Signature, BigInteger Modulus,
53 BigInteger Exponent, ICommunicationLayer? Client)
54 {
55 BigInteger S = EllipticCurve.ToInt(Signature, true);
56 ModulusP ModN = new(Modulus);
57 BigInteger EM = 1;
58 bool HasSniffer = Client?.HasSniffers ?? false;
59 StringBuilder? Msg = HasSniffer ? new StringBuilder() : null;
60
61 if (HasSniffer)
62 {
63 Msg!.AppendLine("RSS-PKCS1 signature verification parameters:");
64 Msg.Append("n (Modulus, dec): ");
65 Msg.AppendLine(Modulus.ToString(CultureInfo.InvariantCulture));
66 Msg.Append("e (Exponent, dec): ");
67 Msg.AppendLine(Exponent.ToString(CultureInfo.InvariantCulture));
68 Msg.Append("S (Signature, dec): ");
69 Msg.AppendLine(S.ToString(CultureInfo.InvariantCulture));
70 Msg.Append("Message (hex): ");
71 Msg.AppendLine(Hashes.BinaryToString(Data));
72 }
73
74 while (!Exponent.IsZero)
75 {
76 if (!Exponent.IsEven)
77 EM = ModN.Multiply(EM, S);
78
79 Exponent >>= 1;
80 S = ModN.Multiply(S, S);
81 }
82
83 int K = Modulus.GetByteCount(true);
84 byte[] EncodedMessage = EM.ToByteArray(true, true);
85
86 if (EncodedMessage.Length > K)
87 {
88 if (HasSniffer)
89 {
90 Client!.Information(Msg!.ToString());
91 Client.Error("Encoded message too long. Invalid signature.");
92 }
93
94 return false;
95 }
96
97 int c = EncodedMessage.Length;
98 if (c < K)
99 {
100 byte[] Padded = new byte[K];
101 Buffer.BlockCopy(EncodedMessage, 0, Padded, K - c, c);
102 EncodedMessage = Padded;
103 }
104
105 if (HasSniffer)
106 {
107 Msg!.Append("EM = S^e (hex): ");
108 Msg.AppendLine(Hashes.BinaryToString(EncodedMessage));
109 }
110
111 byte[] HashDigest = this.HashAlgorithm(Data);
112
113 if (HasSniffer)
114 {
115 Msg!.Append("Hash Digest (hex): ");
116 Msg.AppendLine(Hashes.BinaryToString(HashDigest));
117 }
118
119 AsnWriter w = new(AsnEncodingRules.DER);
120
121 w.PushSequence();
122 w.PushSequence();
123 w.WriteObjectIdentifier(this.HashAlgorithmOid);
124 w.WriteNull();
125 w.PopSequence();
126 w.WriteOctetString(HashDigest);
127 w.PopSequence();
128
129 byte[] DigestInfo = w.Encode();
130
131 if (HasSniffer)
132 {
133 Msg!.Append("DigestInfo (hex): ");
134 Msg.AppendLine(Hashes.BinaryToString(DigestInfo));
135 }
136
137 if (c < DigestInfo.Length + 11)
138 {
139 if (HasSniffer)
140 {
141 Client!.Information(Msg!.ToString());
142 Client.Error("Encoded message & DigestInfo length mismatch. Invalid signature.");
143 }
144
145 return false;
146 }
147
148 if (EncodedMessage[0] != 0x00 || EncodedMessage[1] != 0x01)
149 {
150 if (HasSniffer)
151 {
152 Client!.Information(Msg!.ToString());
153 Client.Error("Encoded message not prefixed correctly. Invalid signature.");
154 }
155
156 return false;
157 }
158
159 int Index = 2;
160
161 while (Index < c && EncodedMessage[Index] == 0xff)
162 Index++;
163
164 if (Index < 10 || Index >= c || EncodedMessage[Index] != 0x00)
165 {
166 if (HasSniffer)
167 {
168 Client!.Information(Msg!.ToString());
169 Client.Error("Encoded message not padded correctly. Invalid signature.");
170 }
171
172 return false;
173 }
174
175 Index++;
176
177 if (c - Index + 1 != DigestInfo.Length)
178 {
179 if (HasSniffer)
180 {
181 Client!.Information(Msg!.ToString());
182 Client.Error("Padding length not correct. Invalid signature.");
183 }
184
185 return false;
186 }
187
188 for (int i = 0; i < DigestInfo.Length; i++)
189 {
190 if (EncodedMessage[Index + i] != DigestInfo[i])
191 {
192 if (HasSniffer)
193 {
194 Client!.Information(Msg!.ToString());
195 Client.Error("DigestInfo not encoded correctly into encoded message. Invalid signature.");
196 }
197
198 return false;
199 }
200 }
201
202 if (HasSniffer)
203 Client!.Information(Msg!.ToString());
204
205 return true;
206 }
207
211 public abstract HashFunctionArray HashAlgorithm { get; }
212
216 public abstract string HashAlgorithmOid { get; }
217 }
218}
Static class for parsing and decoding security objects encoded using Abstract Syntax Notation 1 (ASN....
Definition: ASN1.cs:22
static int ReportAlgorithmUse(string Name)
Records an Elliptic Curve has been used.
Definition: ASN1.cs:420
The RSA Public Key object does not have an OID of its own. Instead, it uses the OID of rsaEncryption ...
Definition: RsaPublicKey.cs:12
override bool VerifySignature(byte[] Data, byte[] Signature, IPublicKey PublicKey, ICommunicationLayer? Client)
Verifies a digital signature.
Definition: RsaAlgorithm.cs:26
bool VerifySignatureRsaPkcs1(byte[] Data, byte[] Signature, BigInteger Modulus, BigInteger Exponent, ICommunicationLayer? Client)
Verifies a digital signature, using RSA PKCS#1 v1.5.
Definition: RsaAlgorithm.cs:52
abstract string HashAlgorithmOid
OID of Hash algorithm to use.
abstract HashFunctionArray HashAlgorithm
Hash algorithm to use.
Abstract base class for signature algorithms, as defined in RFC 5280.
Abstract base class for elliptic curves.
static BigInteger ToInt(byte[] Binary, bool BigEndian)
Converts a little-endian binary representation of a big integer to a BigInteger.
Integer arithmetic, modulus a prime.
Definition: ModulusP.cs:10
BigInteger Multiply(BigInteger a, BigInteger b)
Multiplies two numbers, modulus p
Definition: ModulusP.cs:80
Contains methods for simple hash calculations.
Definition: Hashes.cs:57
static string BinaryToString(byte[] Data)
Converts an array of bytes to a string with their hexadecimal representations (in lower case).
Definition: Hashes.cs:63
void Information(string Comment)
Called to inform the viewer of something.
void Error(string Error)
Called to inform the viewer of an error state.
Interface for observable classes implementing communication protocols.
bool HasSniffers
If there are sniffers registered on the object.
delegate byte[] HashFunctionArray(byte[] Data)
Delegate to hash function.