source: trunk/CrypPlugins/PKCS1/Library/SigValidator.cs @ 1893

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

renamed some classes for the sake of consistency

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