1 // Transport Security Layer (TLS)
2 // Copyright (c) 2003-2004 Carlos Guzman Alvarez
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 using System
.Security
.Cryptography
;
28 namespace Mono
.Security
.Protocol
.Tls
30 internal class SslHandshakeHash
: System
.Security
.Cryptography
.HashAlgorithm
34 private HashAlgorithm md5
;
35 private HashAlgorithm sha
;
37 private byte[] secret
;
38 private byte[] innerPadMD5
;
39 private byte[] outerPadMD5
;
40 private byte[] innerPadSHA
;
41 private byte[] outerPadSHA
;
47 public SslHandshakeHash(byte[] secret
)
49 // Create md5 and sha1 hashes
50 this.md5
= HashAlgorithm
.Create("MD5");
51 this.sha
= HashAlgorithm
.Create("SHA1");
54 this.HashSizeValue
= md5
.HashSize
+ sha
.HashSize
;
66 public override void Initialize()
68 this.md5
.Initialize();
69 this.sha
.Initialize();
74 protected override byte[] HashFinal()
81 // Finalize the md5 hash
82 this.md5
.TransformBlock(this.secret
, 0, this.secret
.Length
, this.secret
, 0);
83 this.md5
.TransformFinalBlock(this.innerPadMD5
, 0, this.innerPadMD5
.Length
);
85 byte[] firstResultMD5
= this.md5
.Hash
;
87 this.md5
.Initialize();
88 this.md5
.TransformBlock(this.secret
, 0, this.secret
.Length
, this.secret
, 0);
89 this.md5
.TransformBlock(this.outerPadMD5
, 0, this.outerPadMD5
.Length
, this.outerPadMD5
, 0);
90 this.md5
.TransformFinalBlock(firstResultMD5
, 0, firstResultMD5
.Length
);
92 // Finalize the sha1 hash
93 this.sha
.TransformBlock(this.secret
, 0, this.secret
.Length
, this.secret
, 0);
94 this.sha
.TransformFinalBlock(this.innerPadSHA
, 0, this.innerPadSHA
.Length
);
96 byte[] firstResultSHA
= this.sha
.Hash
;
98 this.sha
.Initialize();
99 this.sha
.TransformBlock(this.secret
, 0, this.secret
.Length
, this.secret
, 0);
100 this.sha
.TransformBlock(this.outerPadSHA
, 0, this.outerPadSHA
.Length
, this.outerPadSHA
, 0);
101 this.sha
.TransformFinalBlock(firstResultSHA
, 0, firstResultSHA
.Length
);
105 byte[] result
= new byte[36];
107 Buffer
.BlockCopy(this.md5
.Hash
, 0, result
, 0, 16);
108 Buffer
.BlockCopy(this.sha
.Hash
, 0, result
, 16, 20);
113 protected override void HashCore(byte[] array
, int ibStart
, int cbSize
)
120 this.md5
.TransformBlock(array
, ibStart
, cbSize
, array
, ibStart
);
121 this.sha
.TransformBlock(array
, ibStart
, cbSize
, array
, ibStart
);
124 public byte[] CreateSignature(RSA rsa
)
128 throw new CryptographicUnexpectedOperationException ("missing key");
131 RSASslSignatureFormatter f
= new RSASslSignatureFormatter(rsa
);
132 f
.SetHashAlgorithm("MD5SHA1");
134 return f
.CreateSignature(this.Hash
);
137 public bool VerifySignature(RSA rsa
, byte[] rgbSignature
)
141 throw new CryptographicUnexpectedOperationException ("missing key");
143 if (rgbSignature
== null)
145 throw new ArgumentNullException ("rgbSignature");
148 RSASslSignatureDeformatter d
= new RSASslSignatureDeformatter(rsa
);
149 d
.SetHashAlgorithm("MD5SHA1");
151 return d
.VerifySignature(this.Hash
, rgbSignature
);
156 #region Private Methods
158 private void initializePad()
161 this.innerPadMD5
= new byte[48];
162 this.outerPadMD5
= new byte[48];
164 /* Pad the key for inner and outer digest */
165 for (int i
= 0; i
< 48; ++i
)
167 this.innerPadMD5
[i
] = 0x36;
168 this.outerPadMD5
[i
] = 0x5C;
172 this.innerPadSHA
= new byte[40];
173 this.outerPadSHA
= new byte[40];
175 /* Pad the key for inner and outer digest */
176 for (int i
= 0; i
< 40; ++i
)
178 this.innerPadSHA
[i
] = 0x36;
179 this.outerPadSHA
[i
] = 0x5C;