StrongNameKeyPair.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // System.Reflection.StrongNameKeyPair.cs
  3. //
  4. // Authors:
  5. // Kevin Winchester ([email protected])
  6. // Sebastien Pouliot ([email protected])
  7. //
  8. // (C) 2002 Kevin Winchester
  9. // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
  10. //
  11. using System.IO;
  12. namespace System.Reflection {
  13. [Serializable]
  14. public class StrongNameKeyPair
  15. {
  16. private byte[] keyPair;
  17. private byte[] publicKey;
  18. private int bitLen;
  19. private bool keypairValid;
  20. public StrongNameKeyPair (byte[] keyPairArray)
  21. {
  22. if (keyPairArray == null)
  23. throw new ArgumentNullException ("keyPairArray");
  24. keypairValid = Validate (keyPairArray);
  25. }
  26. public StrongNameKeyPair (FileStream keyPairFile)
  27. {
  28. if (keyPairFile == null)
  29. throw new ArgumentNullException ("keyPairFile");
  30. byte[] input = new byte [keyPairFile.Length];
  31. keyPairFile.Read (input, 0, input.Length);
  32. keypairValid = Validate (input);
  33. }
  34. [MonoTODO("We do not, yet, support keypair persistance")]
  35. public StrongNameKeyPair (string keyPairContainer)
  36. {
  37. // named key container
  38. if (keyPairContainer == null)
  39. throw new ArgumentNullException ("keyPairContainer");
  40. // only RSA ? or both RSA and DSA ?
  41. throw new NotImplementedException ();
  42. }
  43. private bool Validate (byte[] keypair) {
  44. // Type - PRIVATEKEYBLOB (0x07)
  45. if (keypair[0] != 0x07)
  46. return false;
  47. // Version - Always CUR_BLOB_VERSION (0x02)
  48. if (keypair[1] != 0x02)
  49. return false;
  50. // RESERVED - Always 0
  51. if ((keypair[2] != 0x00) || (keypair[3] != 0x00))
  52. return false;
  53. // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
  54. if ((keypair[4] != 0x00) || (keypair[5] != 0x24) || (keypair[6] != 0x00) || (keypair[7] != 0x00))
  55. return false;
  56. // Magic - RSA2 (ASCII in hex)
  57. if ((keypair[8] != 0x52) || (keypair[9] != 0x53) || (keypair[10] != 0x41) || (keypair[11] != 0x32))
  58. return false;
  59. // bitlen - ex: 1024 - must be a multiple of 8
  60. bitLen = (keypair[15] << 24) + (keypair[14] << 16) + (keypair[13] << 8) + keypair[12];
  61. if (bitLen % 8 != 0)
  62. return false;
  63. // public exponent (DWORD)
  64. // modulus
  65. // private key
  66. keyPair = keypair;
  67. return true;
  68. }
  69. public byte[] PublicKey {
  70. get {
  71. if (!keypairValid)
  72. throw new ArgumentException ("invalid keypair");
  73. // first call (will be cached for all subsequent calls)
  74. if (publicKey == null) {
  75. publicKey = new byte [(bitLen >> 3) + 32];
  76. // The first 12 bytes are documented at:
  77. // http://msdn.microsoft.com/library/en-us/cprefadd/html/grfungethashfromfile.asp
  78. // ALG_ID - Signature
  79. publicKey[0] = keyPair[4];
  80. publicKey[1] = keyPair[5];
  81. publicKey[2] = keyPair[6];
  82. publicKey[3] = keyPair[7];
  83. // ALG_ID - Hash
  84. publicKey[4] = 0x04;
  85. publicKey[5] = 0x80;
  86. publicKey[6] = 0x00;
  87. publicKey[7] = 0x00;
  88. // Length of Public Key (in bytes)
  89. int lastPart = publicKey.Length - 12;
  90. publicKey[8] = (byte)(lastPart % 256);
  91. publicKey[9] = (byte)(lastPart / 256); // just in case
  92. publicKey[10] = 0x00;
  93. publicKey[11] = 0x00;
  94. // Ok from here - Same structure as keypair - expect for public key
  95. publicKey[12] = 0x06; // PUBLICKEYBLOB
  96. // we can copy this part
  97. Array.Copy (keyPair, 1, publicKey, 13, publicKey.Length - 13);
  98. // and make a small adjustment
  99. publicKey[23] = 0x31; // (RSA1 not RSA2)
  100. }
  101. return publicKey;
  102. }
  103. }
  104. }
  105. }