Skip to content

Commit

Permalink
add custom StrongNameKeyPair
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonCropp committed Aug 18, 2019
1 parent 500d022 commit e541e2b
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 3 deletions.
9 changes: 7 additions & 2 deletions Mono.Cecil/ModuleDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
using System.IO;
using System.Threading;
using SR = System.Reflection;
#if (NETSTANDARD)
using StrongNameKeyPair=Mono.Cecil.StrongNameKeyPair;
#else
using StrongNameKeyPair=System.Reflection.StrongNameKeyPair;
#endif

using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
Expand Down Expand Up @@ -185,7 +190,7 @@ public sealed class WriterParameters {
bool write_symbols;
byte [] key_blob;
string key_container;
SR.StrongNameKeyPair key_pair;
StrongNameKeyPair key_pair;

public uint? Timestamp {
get { return timestamp; }
Expand Down Expand Up @@ -221,7 +226,7 @@ public string StrongNameKeyContainer {
set { key_container = value; }
}

public SR.StrongNameKeyPair StrongNameKeyPair {
public StrongNameKeyPair StrongNameKeyPair {
get { return key_pair; }
set { key_pair = value; }
}
Expand Down
132 changes: 132 additions & 0 deletions Mono.Cecil/StrongNameKeyPair.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#if (NETSTANDARD)
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Cryptography;

namespace Mono.Cecil {
[Serializable]
public class StrongNameKeyPair : ISerializable {
bool _keyPairExported;
byte [] _keyPairArray;
string _keyPairContainer;
byte [] _publicKey;

public byte [] PublicKey {
[SecuritySafeCritical]
get {
if (_publicKey == null) {
_publicKey = ComputePublicKey ();
}

byte [] array = new byte[_publicKey.Length];
Array.Copy (_publicKey, array, _publicKey.Length);
return array;
}
}

public StrongNameKeyPair (FileStream keyPairFile)
{
if (keyPairFile == null) {
throw new ArgumentNullException ("keyPairFile");
}

var num = (int) keyPairFile.Length;
_keyPairArray = new byte[num];
keyPairFile.Read (_keyPairArray, 0, num);
_keyPairExported = true;
}

public StrongNameKeyPair (byte [] keyPairArray)
{
if (keyPairArray == null) {
throw new ArgumentNullException ("keyPairArray");
}

_keyPairArray = new byte[keyPairArray.Length];
Array.Copy (keyPairArray, _keyPairArray, keyPairArray.Length);
_keyPairExported = true;
}

public StrongNameKeyPair (string keyPairContainer)
{
if (keyPairContainer == null) {
throw new ArgumentNullException ("keyPairContainer");
}

_keyPairContainer = keyPairContainer;
_keyPairExported = false;
}

protected StrongNameKeyPair (SerializationInfo info, StreamingContext context)
{
_keyPairExported = (bool) info.GetValue ("_keyPairExported", typeof(bool));
_keyPairArray = (byte []) info.GetValue ("_keyPairArray", typeof(byte []));
_keyPairContainer = (string) info.GetValue ("_keyPairContainer", typeof(string));
_publicKey = (byte []) info.GetValue ("_publicKey", typeof(byte []));
}

byte [] ComputePublicKey ()
{
using (var rsa = Mixin.CreateRSA (this)) {
var cspBlob = ToCapiPublicKeyBlob (rsa);
var publicKey = new byte[12 + cspBlob.Length];
Buffer.BlockCopy (cspBlob, 0, publicKey, 12, cspBlob.Length);
// The first 12 bytes are documented at:
// http://msdn.microsoft.com/library/en-us/cprefadd/html/grfungethashfromfile.asp
// ALG_ID - Signature
publicKey [1] = 36;
// ALG_ID - Hash
publicKey [4] = 4;
publicKey [5] = 128;
// Length of Public Key (in bytes)
publicKey [8] = (byte) (cspBlob.Length >> 0);
publicKey [9] = (byte) (cspBlob.Length >> 8);
publicKey [10] = (byte) (cspBlob.Length >> 16);
publicKey [11] = (byte) (cspBlob.Length >> 24);
return publicKey;
}
}

void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
{
info.AddValue ("_keyPairExported", _keyPairExported);
info.AddValue ("_keyPairArray", _keyPairArray);
info.AddValue ("_keyPairContainer", _keyPairContainer);
info.AddValue ("_publicKey", _publicKey);
}

static byte [] ToCapiPublicKeyBlob (RSA rsa)
{
var rsap = rsa.ExportParameters (false);
var blob = new byte[rsap.Modulus.Length + 20];
blob [0] = 0x06; // PUBLICKEYBLOB (0x06)
blob [1] = 0x02; // Version (0x02)
blob [2] = 0x00; // Reserved (word)
blob [3] = 0x00;
blob [5] = 0x24; // ALGID
WriteUInt32LE (blob, 8, 0x31415352); // DWORD magic = RSA1
WriteUInt32LE (blob, 12, (uint) rsap.Modulus.Length << 3); // DWORD bitlen

// DWORD public exponent
blob [18] = rsap.Exponent [0];
blob [17] = rsap.Exponent [1];
blob [16] = rsap.Exponent [2];

// BYTE modulus[rsapubkey.bitlen/8];
Array.Reverse (rsap.Modulus);
Buffer.BlockCopy (rsap.Modulus, 0, blob, 20, rsap.Modulus.Length);
return blob;
}

static void WriteUInt32LE (byte [] bytes, int offset, uint value)
{
bytes [offset + 3] = (byte) (value >> 24);
bytes [offset + 2] = (byte) (value >> 16);
bytes [offset + 1] = (byte) (value >> 8);
bytes [offset] = (byte) value;
}
}
}
#endif
23 changes: 22 additions & 1 deletion Mono.Security.Cryptography/CryptoService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@

using System;
using System.IO;
using System.Reflection;
#if (NETSTANDARD)
using StrongNameKeyPair=Mono.Cecil.StrongNameKeyPair;
#else
using StrongNameKeyPair=System.Reflection.StrongNameKeyPair;
#endif
using System.Security.Cryptography;
using System.Runtime.Serialization;

Expand Down Expand Up @@ -191,6 +195,23 @@ public static RSA CreateRSA (this WriterParameters writer_parameters)
return new RSACryptoServiceProvider (parameters);
}

public static RSA CreateRSA (this StrongNameKeyPair key_pair)
{
byte [] key;
string key_container;

if (!TryGetKeyContainer (key_pair, out key, out key_container))
return CryptoConvert.FromCapiKeyBlob (key);

var parameters = new CspParameters {
Flags = CspProviderFlags.UseMachineKeyStore,
KeyContainerName = key_container,
KeyNumber = 2,
};

return new RSACryptoServiceProvider (parameters);
}

static bool TryGetKeyContainer (ISerializable key_pair, out byte [] key, out string key_container)
{
var info = new SerializationInfo (typeof (StrongNameKeyPair), new FormatterConverter ());
Expand Down

0 comments on commit e541e2b

Please sign in to comment.