source: trunk/PKCS1/Library/RSAValidator.cs @ 1650

Last change on this file since 1650 was 1650, checked in by schomburg, 11 years ago

initial commit of PKCS1 Plugin

File size: 8.4 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using Org.BouncyCastle.Crypto;
6using Org.BouncyCastle.Crypto.Encodings;
7using Org.BouncyCastle.Crypto.Engines;
8using Org.BouncyCastle.Math;
9using Org.BouncyCastle.Crypto.Parameters;
10using Org.BouncyCastle.Utilities.Encoders;
11using Org.BouncyCastle.Security;
12
13namespace PKCS1.Library
14{
15    class RSAValidator
16    {
17        HashFunctionIdent funcIdent = null;
18
19        #region verify Signatures
20
21        private bool verifySig(ISigner verifier, string message, byte[] signature)
22        {           
23            verifier.Init(false, RSAKeyManager.getInstance().getPubKey());           
24            byte[] messageInBytes = Encoding.ASCII.GetBytes(message);
25            verifier.BlockUpdate(messageInBytes, 0, messageInBytes.Length); // update bekommt klartextnachricht als param           
26            return verifier.VerifySignature(signature); // input ist verschlüsselte Nachricht
27        }
28
29        public bool verifyRsaSignature(string message, byte[] signature)
30        {
31            IAsymmetricBlockCipher eng = new Pkcs1Encoding(new RsaEngine());
32            //IAsymmetricBlockCipher eng = new RsaEngine();
33            eng.Init(false, RSAKeyManager.getInstance().getPubKey());
34
35            try
36            {
37                //byte[] messageInBytes = Encoding.ASCII.GetBytes(message);
38                byte[] data = eng.ProcessBlock(signature, 0, signature.Length);
39                funcIdent = this.extractHashFunction(Encoding.ASCII.GetString(Hex.Encode(data)));
40
41                if (null != funcIdent)
42                {
43                    string signerIdent = funcIdent.diplayName + "withRSA";
44                    ISigner verifier = SignerUtilities.GetSigner(signerIdent);
45                    return this.verifySig(verifier, message, signature);
46                }
47            }
48            catch(Exception e)
49            {
50                return false;
51            }
52
53            return false;
54        }
55
56        public string getHashFunctionName()
57        {
58            if (this.funcIdent != null)
59            {
60                return funcIdent.diplayName;
61            }
62            return String.Empty;
63        }
64
65        private HashFunctionIdent extractHashFunction(string input)
66        {
67            string inputString = input.ToLower();
68
69            if (inputString.StartsWith(HashFunctionHandler.SHA1.DERIdent.ToLower()))
70            {
71                return HashFunctionHandler.SHA1;
72            }
73            else if (inputString.StartsWith(HashFunctionHandler.SHA256.DERIdent.ToLower()))
74            {
75                return HashFunctionHandler.SHA256;
76            }
77            else if (inputString.StartsWith(HashFunctionHandler.SHA384.DERIdent.ToLower()))
78            {
79                return HashFunctionHandler.SHA384;
80            }
81            else if (inputString.StartsWith(HashFunctionHandler.SHA512.DERIdent.ToLower()))
82            {
83                return HashFunctionHandler.SHA512;
84            }
85            else if (inputString.StartsWith(HashFunctionHandler.MD2.DERIdent.ToLower()))
86            {
87                return HashFunctionHandler.MD2;
88            }
89            else if (inputString.StartsWith(HashFunctionHandler.MD5.DERIdent.ToLower()))
90            {
91                return HashFunctionHandler.MD5;
92            }
93
94            return null;
95        }
96
97        public bool verifyRsaSignatureWithFlaw(string message, byte[] signature)
98        {
99            BigInteger signatureBigInt = new BigInteger(1,signature);
100            byte[] messageInBytes = Encoding.ASCII.GetBytes(message);           
101
102            RsaKeyParameters pubkeyParam = (RsaKeyParameters)RSAKeyManager.getInstance().getPubKey();
103            BigInteger exponent = pubkeyParam.Exponent;
104            BigInteger modulus = pubkeyParam.Modulus;
105
106            byte[] sigDecrypted = (signatureBigInt.ModPow(exponent, modulus)).ToByteArray();
107            byte[] block = this.DerEncode(sigDecrypted); // hiernach steht DERIdent und hash am anfang des arrays, danach garbage
108
109            funcIdent = this.extractHashFunction(Encoding.ASCII.GetString(Hex.Encode(block)));
110
111            // SHA1, Digest length: 160 Bit
112            if(funcIdent == HashFunctionHandler.SHA1)
113            {
114                return this.verifySigWithoutPad(block, messageInBytes, HashFunctionHandler.SHA1, 20);
115            }
116
117            // SHA-256, Digest length: 256 Bit
118            if(funcIdent == HashFunctionHandler.SHA256)
119            {
120                return this.verifySigWithoutPad(block, messageInBytes, HashFunctionHandler.SHA256, 32);
121            }
122
123            // SHA-384, Digest length: 384 Bit
124            if(funcIdent == HashFunctionHandler.SHA384)
125            {
126                return this.verifySigWithoutPad(block, messageInBytes, HashFunctionHandler.SHA384, 48);
127            }
128
129            // SHA-512, Digest length: 512 Bit
130            if(funcIdent == HashFunctionHandler.SHA512)
131            {
132                return this.verifySigWithoutPad(block, messageInBytes, HashFunctionHandler.SHA512, 64);
133            }
134
135            // MD2, Digest length: 120 Bit
136            if(funcIdent == HashFunctionHandler.MD2)
137            {
138                return this.verifySigWithoutPad(block, messageInBytes, HashFunctionHandler.MD2, 15);
139            }
140
141            // MD5, Digest length: 120 Bit
142            if(funcIdent == HashFunctionHandler.MD5)
143            {
144                return this.verifySigWithoutPad(block, messageInBytes, HashFunctionHandler.MD5, 15);
145            }
146
147            return false;
148        }
149
150        private bool verifySigWithoutPad(byte[] sigWithoutPad, byte[] message, HashFunctionIdent hashFuncIdent, int digestLength)
151        {
152            //TODO Längen überprüfen!
153            string blockString = Encoding.ASCII.GetString(Hex.Encode(sigWithoutPad)).ToLower();
154
155            byte[] hashDigestFromSig = new byte[digestLength];
156            int endOfIdent = hashFuncIdent.DERIdent.Length / 2;
157            Array.Copy(sigWithoutPad, endOfIdent, hashDigestFromSig, 0, digestLength);
158
159            IDigest hashFunctionDigest = DigestUtilities.GetDigest(hashFuncIdent.diplayName);
160            byte[] hashDigestMessage = Hashfunction.generateHashDigest(message, hashFuncIdent);
161
162            return this.compareByteArrays(hashDigestFromSig, hashDigestMessage);
163        }
164
165        private bool compareByteArrays(byte[] input1, byte[] input2)
166        {
167            bool bEqual = false;
168
169            string test1 = Encoding.ASCII.GetString(Hex.Encode(input1));
170            string test2 = Encoding.ASCII.GetString(Hex.Encode(input2));
171
172            if (input1.Length == input2.Length)
173            {
174                int i = 0;
175                while ((i < input1.Length) && (input1[i] == input2[i]))
176                {
177                    i += 1;
178                }
179                if (i == input1.Length)
180                {
181                    bEqual = true;
182                }
183            }
184            return bEqual;
185        }
186
187        private byte[] DerEncode(byte[] block)
188        {
189            // hier 0001 checken, dann FF Bytes skippen, dann HW zurück geben, Länge auslesen?           
190            byte type = block[0];
191
192            if (type != 1 && type != 2)
193            {
194                // TODO Exception schmeissen
195                //throw new InvalidCipherTextException("unknown block type");
196            }
197
198            int start;
199            for (start = 1; start != block.Length; start++)
200            {
201                byte pad = block[start];
202
203                if (pad == 0)
204                {
205                    break;
206                }
207
208                if (type == 1 && pad != (byte)0xff)
209                {
210                    throw new InvalidCipherTextException("block padding incorrect");
211                }
212            }
213            start++;           // data should start at the next byte
214
215            /*
216            if (start > block.Length || start < HeaderLength)
217            {
218                throw new InvalidCipherTextException("no data in block");
219            }*/
220
221            byte[] result = new byte[block.Length - start];
222            Array.Copy(block, start, result, 0, result.Length);
223
224            return result; // anschliessend muss punkt 2.3 kommen
225        }
226
227        #endregion // verify Signatures
228
229
230    }
231}
Note: See TracBrowser for help on using the repository browser.