Skip to content

Commit 12da1bf

Browse files
atykhyyjbevain
authored andcommitted
Don't rely on StrongNameKeyPair (#548)
1 parent b2d248c commit 12da1bf

File tree

4 files changed

+99
-11
lines changed

4 files changed

+99
-11
lines changed

Mono.Cecil/AssemblyWriter.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ static void Write (ModuleDefinition module, Disposable<Stream> stream, WriterPar
102102
if (symbol_writer_provider == null && parameters.WriteSymbols)
103103
symbol_writer_provider = new DefaultSymbolWriterProvider ();
104104

105-
if (parameters.StrongNameKeyPair != null && name != null) {
106-
name.PublicKey = parameters.StrongNameKeyPair.PublicKey;
105+
if (parameters.HasStrongNameKey && name != null) {
106+
name.PublicKey = CryptoService.GetPublicKey (parameters);
107107
module.Attributes |= ModuleAttributes.StrongNameSigned;
108108
}
109109

@@ -125,8 +125,8 @@ static void Write (ModuleDefinition module, Disposable<Stream> stream, WriterPar
125125
stream.value.SetLength (0);
126126
writer.WriteImage ();
127127

128-
if (parameters.StrongNameKeyPair != null)
129-
CryptoService.StrongName (stream.value, writer, parameters.StrongNameKeyPair);
128+
if (parameters.HasStrongNameKey)
129+
CryptoService.StrongName (stream.value, writer, parameters);
130130
}
131131
} finally {
132132
module.metadata_builder = null;

Mono.Cecil/ModuleDefinition.cs

+16
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ public sealed class WriterParameters {
183183
Stream symbol_stream;
184184
ISymbolWriterProvider symbol_writer_provider;
185185
bool write_symbols;
186+
byte [] key_blob;
187+
string key_container;
186188
SR.StrongNameKeyPair key_pair;
187189

188190
public uint? Timestamp {
@@ -205,6 +207,20 @@ public bool WriteSymbols {
205207
set { write_symbols = value; }
206208
}
207209

210+
public bool HasStrongNameKey {
211+
get { return key_pair != null || key_blob != null || key_container != null; }
212+
}
213+
214+
public byte [] StrongNameKeyBlob {
215+
get { return key_blob; }
216+
set { key_blob = value; }
217+
}
218+
219+
public string StrongNameKeyContainer {
220+
get { return key_container; }
221+
set { key_container = value; }
222+
}
223+
208224
public SR.StrongNameKeyPair StrongNameKeyPair {
209225
get { return key_pair; }
210226
set { key_pair = value; }

Mono.Security.Cryptography/CryptoConvert.cs

+46
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ static private uint ToUInt32LE (byte [] bytes, int offset)
4444
return (uint)((bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]);
4545
}
4646

47+
static private byte [] GetBytesLE (int val)
48+
{
49+
return new byte [] {
50+
(byte) (val & 0xff),
51+
(byte) ((val >> 8) & 0xff),
52+
(byte) ((val >> 16) & 0xff),
53+
(byte) ((val >> 24) & 0xff)
54+
};
55+
}
56+
4757
static private byte[] Trim (byte[] array)
4858
{
4959
for (int i=0; i < array.Length; i++) {
@@ -240,5 +250,41 @@ static public RSA FromCapiKeyBlob (byte[] blob, int offset)
240250
}
241251
throw new CryptographicException ("Unknown blob format.");
242252
}
253+
254+
static public byte[] ToCapiPublicKeyBlob (RSA rsa)
255+
{
256+
RSAParameters p = rsa.ExportParameters (false);
257+
int keyLength = p.Modulus.Length; // in bytes
258+
byte[] blob = new byte [20 + keyLength];
259+
260+
blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06)
261+
blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
262+
// [2], [3] // RESERVED - Always 0
263+
blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
264+
blob [8] = 0x52; // Magic - RSA1 (ASCII in hex)
265+
blob [9] = 0x53;
266+
blob [10] = 0x41;
267+
blob [11] = 0x31;
268+
269+
byte[] bitlen = GetBytesLE (keyLength << 3);
270+
blob [12] = bitlen [0]; // bitlen
271+
blob [13] = bitlen [1];
272+
blob [14] = bitlen [2];
273+
blob [15] = bitlen [3];
274+
275+
// public exponent (DWORD)
276+
int pos = 16;
277+
int n = p.Exponent.Length;
278+
while (n > 0)
279+
blob [pos++] = p.Exponent [--n];
280+
// modulus
281+
pos = 20;
282+
byte[] part = p.Modulus;
283+
int len = part.Length;
284+
Array.Reverse (part, 0, len);
285+
Buffer.BlockCopy (part, 0, blob, pos, len);
286+
pos += len;
287+
return blob;
288+
}
243289
}
244290
}

Mono.Security.Cryptography/CryptoService.cs

+33-7
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,33 @@ namespace Mono.Cecil {
2626

2727
static class CryptoService {
2828

29-
public static void StrongName (Stream stream, ImageWriter writer, StrongNameKeyPair key_pair)
29+
public static byte [] GetPublicKey (WriterParameters parameters)
30+
{
31+
using (var rsa = parameters.CreateRSA ()) {
32+
var cspBlob = CryptoConvert.ToCapiPublicKeyBlob (rsa);
33+
var publicKey = new byte [12 + cspBlob.Length];
34+
Buffer.BlockCopy (cspBlob, 0, publicKey, 12, cspBlob.Length);
35+
// The first 12 bytes are documented at:
36+
// http://msdn.microsoft.com/library/en-us/cprefadd/html/grfungethashfromfile.asp
37+
// ALG_ID - Signature
38+
publicKey [1] = 36;
39+
// ALG_ID - Hash
40+
publicKey [4] = 4;
41+
publicKey [5] = 128;
42+
// Length of Public Key (in bytes)
43+
publicKey [8] = (byte) (cspBlob.Length >> 0);
44+
publicKey [9] = (byte) (cspBlob.Length >> 8);
45+
publicKey [10] = (byte) (cspBlob.Length >> 16);
46+
publicKey [11] = (byte) (cspBlob.Length >> 24);
47+
return publicKey;
48+
}
49+
}
50+
51+
public static void StrongName (Stream stream, ImageWriter writer, WriterParameters parameters)
3052
{
3153
int strong_name_pointer;
3254

33-
var strong_name = CreateStrongName (key_pair, HashStream (stream, writer, out strong_name_pointer));
55+
var strong_name = CreateStrongName (parameters, HashStream (stream, writer, out strong_name_pointer));
3456
PatchStrongName (stream, strong_name_pointer, strong_name);
3557
}
3658

@@ -40,11 +62,11 @@ static void PatchStrongName (Stream stream, int strong_name_pointer, byte [] str
4062
stream.Write (strong_name, 0, strong_name.Length);
4163
}
4264

43-
static byte [] CreateStrongName (StrongNameKeyPair key_pair, byte [] hash)
65+
static byte [] CreateStrongName (WriterParameters parameters, byte [] hash)
4466
{
4567
const string hash_algo = "SHA1";
4668

47-
using (var rsa = key_pair.CreateRSA ()) {
69+
using (var rsa = parameters.CreateRSA ()) {
4870
var formatter = new RSAPKCS1SignatureFormatter (rsa);
4971
formatter.SetHashAlgorithm (hash_algo);
5072

@@ -74,7 +96,6 @@ static byte [] HashStream (Stream stream, ImageWriter writer, out int strong_nam
7496
var sha1 = new SHA1Managed ();
7597
var buffer = new byte [buffer_size];
7698
using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write)) {
77-
7899
stream.Seek (0, SeekOrigin.Begin);
79100
CopyStreamChunk (stream, crypto_stream, buffer, header_size);
80101

@@ -148,12 +169,17 @@ public static Guid ComputeGuid (byte [] hash)
148169

149170
static partial class Mixin {
150171

151-
public static RSA CreateRSA (this StrongNameKeyPair key_pair)
172+
public static RSA CreateRSA (this WriterParameters writer_parameters)
152173
{
153174
byte [] key;
154175
string key_container;
155176

156-
if (!TryGetKeyContainer (key_pair, out key, out key_container))
177+
if (writer_parameters.StrongNameKeyBlob != null)
178+
return CryptoConvert.FromCapiKeyBlob (writer_parameters.StrongNameKeyBlob);
179+
180+
if (writer_parameters.StrongNameKeyContainer != null)
181+
key_container = writer_parameters.StrongNameKeyContainer;
182+
else if (!TryGetKeyContainer (writer_parameters.StrongNameKeyPair, out key, out key_container))
157183
return CryptoConvert.FromCapiKeyBlob (key);
158184

159185
var parameters = new CspParameters {

0 commit comments

Comments
 (0)