Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.Cecil/0.9.5/Mono.Cecil-0.9.5/Mono.Cecil/Mono.Security.Cryptography/CryptoService.cs @ 17317

Last change on this file since 17317 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 5.4 KB
Line 
1//
2// CryptoService.cs
3//
4// Author:
5//   Jb Evain (jbevain@gmail.com)
6//
7// Copyright (c) 2008 - 2011 Jb Evain
8//
9// Permission is hereby granted, free of charge, to any person obtaining
10// a copy of this software and associated documentation files (the
11// "Software"), to deal in the Software without restriction, including
12// without limitation the rights to use, copy, modify, merge, publish,
13// distribute, sublicense, and/or sell copies of the Software, and to
14// permit persons to whom the Software is furnished to do so, subject to
15// the following conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27//
28
29using System;
30using System.IO;
31using System.Reflection;
32using System.Security.Cryptography;
33
34#if !READ_ONLY
35
36#if !SILVERLIGHT && !CF
37using System.Runtime.Serialization;
38using Mono.Security.Cryptography;
39#endif
40
41using Mono.Cecil.PE;
42
43namespace Mono.Cecil {
44
45  // Most of this code has been adapted
46  // from Jeroen Frijters' fantastic work
47  // in IKVM.Reflection.Emit. Thanks!
48
49  static class CryptoService {
50
51#if !SILVERLIGHT && !CF
52    public static void StrongName (Stream stream, ImageWriter writer, StrongNameKeyPair key_pair)
53    {
54      int strong_name_pointer;
55
56      var strong_name = CreateStrongName (key_pair, HashStream (stream, writer, out strong_name_pointer));
57      PatchStrongName (stream, strong_name_pointer, strong_name);
58    }
59
60    static void PatchStrongName (Stream stream, int strong_name_pointer, byte [] strong_name)
61    {
62      stream.Seek (strong_name_pointer, SeekOrigin.Begin);
63      stream.Write (strong_name, 0, strong_name.Length);
64    }
65
66    static byte [] CreateStrongName (StrongNameKeyPair key_pair, byte [] hash)
67    {
68      const string hash_algo = "SHA1";
69
70      using (var rsa = key_pair.CreateRSA ()) {
71        var formatter = new RSAPKCS1SignatureFormatter (rsa);
72        formatter.SetHashAlgorithm (hash_algo);
73
74        byte [] signature = formatter.CreateSignature (hash);
75        Array.Reverse (signature);
76
77        return signature;
78      }
79    }
80
81    static byte [] HashStream (Stream stream, ImageWriter writer, out int strong_name_pointer)
82    {
83      const int buffer_size = 8192;
84
85      var text = writer.text;
86      var header_size = (int) writer.GetHeaderSize ();
87      var text_section_pointer = (int) text.PointerToRawData;
88      var strong_name_directory = writer.GetStrongNameSignatureDirectory ();
89
90      if (strong_name_directory.Size == 0)
91        throw new InvalidOperationException ();
92
93      strong_name_pointer = (int) (text_section_pointer
94        + (strong_name_directory.VirtualAddress - text.VirtualAddress));
95      var strong_name_length = (int) strong_name_directory.Size;
96
97      var sha1 = new SHA1Managed ();
98      var buffer = new byte [buffer_size];
99      using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write)) {
100
101        stream.Seek (0, SeekOrigin.Begin);
102        CopyStreamChunk (stream, crypto_stream, buffer, header_size);
103
104        stream.Seek (text_section_pointer, SeekOrigin.Begin);
105        CopyStreamChunk (stream, crypto_stream, buffer, (int) strong_name_pointer - text_section_pointer);
106
107        stream.Seek (strong_name_length, SeekOrigin.Current);
108        CopyStreamChunk (stream, crypto_stream, buffer, (int) (stream.Length - (strong_name_pointer + strong_name_length)));
109      }
110
111      return sha1.Hash;
112    }
113#endif
114    static void CopyStreamChunk (Stream stream, Stream dest_stream, byte [] buffer, int length)
115    {
116      while (length > 0) {
117        int read = stream.Read (buffer, 0, System.Math.Min (buffer.Length, length));
118        dest_stream.Write (buffer, 0, read);
119        length -= read;
120      }
121    }
122
123    public static byte [] ComputeHash (string file)
124    {
125      if (!File.Exists (file))
126        return Empty<byte>.Array;
127
128      const int buffer_size = 8192;
129
130      var sha1 = new SHA1Managed ();
131
132      using (var stream = new FileStream (file, FileMode.Open, FileAccess.Read, FileShare.Read)) {
133
134        var buffer = new byte [buffer_size];
135
136        using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write))
137          CopyStreamChunk (stream, crypto_stream, buffer, (int) stream.Length);
138      }
139
140      return sha1.Hash;
141    }
142  }
143
144#if !SILVERLIGHT && !CF
145  static partial class Mixin {
146
147    public static RSA CreateRSA (this StrongNameKeyPair key_pair)
148    {
149      byte [] key;
150      string key_container;
151
152      if (!TryGetKeyContainer (key_pair, out key, out key_container))
153        return CryptoConvert.FromCapiKeyBlob (key);
154
155      var parameters = new CspParameters {
156        Flags = CspProviderFlags.UseMachineKeyStore,
157        KeyContainerName = key_container,
158        KeyNumber = 2,
159      };
160
161      return new RSACryptoServiceProvider (parameters);
162    }
163
164    static bool TryGetKeyContainer (ISerializable key_pair, out byte [] key, out string key_container)
165    {
166      var info = new SerializationInfo (typeof (StrongNameKeyPair), new FormatterConverter ());
167      key_pair.GetObjectData (info, new StreamingContext ());
168
169      key = (byte []) info.GetValue ("_keyPairArray", typeof (byte []));
170      key_container = info.GetString ("_keyPairContainer");
171      return key_container != null;
172    }
173  }
174#endif
175}
176
177#endif
Note: See TracBrowser for help on using the repository browser.