簡體   English   中英

RSA加密處理無效問題

[英]RSA Encrypt Handle invalid issue

我正在嘗試加密文本,並使用公共私鑰對解密它。 我需要將鍵作為字符串處理。 因此,我將這些密鑰從字符串轉換為RSAParameters。 但是,當我嘗試加密文本時,由於“句柄無效”,它引發了錯誤。

static RSAParameters _publicKey = new RSAParameters();
static RSAParameters _privateKey = new RSAParameters();
static string _strPublicKey = "-----BEGIN PUBLIC KEY-----\r\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsG5sBbnH7gXkrExzNOeK\r\nEjoRDHUH5uU+crH52Z1uXCEx8LiFow8RwrvZGqjYXgBwxzqOQwHJt3utoNVY0niP\r\nHjfPXwKTk79PkeET/mtRar1gEcCOr0/hgHxT3YGlQLw2ugVIulMzlUBRY4rceNv3\r\nEiSZ+4cnO04hJ6UiftrCfwTe6q9Hadp6B6SX+N9hgcHhRX4iR/VYUf/6cvN+NAgb\r\ntuF0Dk61C6ulh2Gvdj2TBCLaq1LPF5H+ghrRxjK/Zn6MG9BW2ju9g8zYKuufaaaM\r\ndbTmN+Z4f27nEOxFq5wWqeaWl53yrMia6xnOi7vtU8zcwBL7jSLgwrkyO8LabCdz\r\neQIDAQAB\r\n-----END PUBLIC KEY-----";
static string _strPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\nMIIEogIBAAKCAQEAsG5sBbnH7gXkrExzNOeKEjoRDHUH5uU+crH52Z1uXCEx8LiF\r\now8RwrvZGqjYXgBwxzqOQwHJt3utoNVY0niPHjfPXwKTk79PkeET/mtRar1gEcCO\r\nr0/hgHxT3YGlQLw2ugVIulMzlUBRY4rceNv3EiSZ+4cnO04hJ6UiftrCfwTe6q9H\r\nadp6B6SX+N9hgcHhRX4iR/VYUf/6cvN+NAgbtuF0Dk61C6ulh2Gvdj2TBCLaq1LP\r\nF5H+ghrRxjK/Zn6MG9BW2ju9g8zYKuufaaaMdbTmN+Z4f27nEOxFq5wWqeaWl53y\r\nrMia6xnOi7vtU8zcwBL7jSLgwrkyO8LabCdzeQIDAQABAoIBAA2z5cvkC/UenA4N\r\nufzn5r9Xpy9Sf5SdRWZfEEqogYPCSECr9CUf7H81W71IU9WpLxkqIRZvMx1/C5Ms\r\nPsPJ/UOZjg+RAak9+I4Z7xWZfC9QGgAG9o4DJD54aYMQqKcIdy+nbWibQaxb3HZg\r\nuJLicqQEF7mDW7atcMHFf5JepzB6LO7u9mfgR03uHQh6r6ym27BTGwssSmEeOeiA\r\n+tOPEhCsbZMSs5+8aGMoV08OqjscytQCWDY8rwA8ZE/qis+cNxKo0OluRTde68mH\r\nbr42CZpNJNulhg4mZyxtrtC+D13VcRpFeKW7WbMBwEUJ8/liUBDvAPLB3Np46FsG\r\njcZfFmkCgYEAtSk5HGEk+y8dyl+l62u7oir5IEZf8vNsMJ+CrpF1C8e6qShRe9uy\r\nJ5pN/4dBb2thknOLsaw6K2qYGNkH3TYSpHusW7v4Iuy6ONmzXHCxcgconzCWJ0HI\r\nLWnYRZAHv8PdOxdFqukjLqFOz6fEyIJ5Ayp+7qxg3QRmE7bwnEwWYK8CgYEA+VEC\r\nBUVUd8tHLqMyaYuv7HXQlQ3J01fobts98k+xqQtKsMUu4SZQ/5uQF8Wk3P6AAKiU\r\ngeD81Fpu4PINrRH97R0twnlWru1fHNSHNenuLASW+3I4l975PhZJc5AeV7VpRcnY\r\nyZCMAKO/XRpfgTEsv5HNfidUsYuJ/9epQzVy6FcCgYAs1V3f6x621ys9OTybrZbL\r\nBG2REjmOq7V7tw4lW7QmzTAhyuuXhoBpkqN4+KU2CNIl51iMCP6AXin0BEoQ8d/d\r\nOwolzbgUFJfll+LunqkbejAQbXrLjlkW/Bnc5U81oyhuBk1khbwCP0N82p01rix6\r\nnxq4wIpcSElm2aBkXeQv2wKBgCvewUhEJtTdhC0Esn44AkDNimJwBq+VrGS1V3Un\r\n6M8iGYZ5bAJaR65ypSxJrvTkI4n6IAeqm1KShyg174ogvFnY5JBv4Xzub+oWy6QF\r\nAc/lDtw4ARVYOutd6JbZKT2twlRxbCAruzbxmV68oUmOaZ1b/pjQOury7tmCDVqy\r\nMQIJAoGAIqUiIAnKLBrXhfN0nqGt2iOnRl31Ef3p/pTNwhUBdJphi/zlE9JHTI2Q\r\nCiLCGyJTpr3FoPjIJZ2P+fRrB3FmVuGNVZw5s8g4ouuDWNyCL/upVwU84eAWMu7P\r\nDsUL5Ia5W7/Cm7d0/nqchUCkRslIsH+bfGj0NZ7qcE5H1D8Ee0A=\r\n-----END RSA PRIVATE KEY-----";
static void Main(string[] args)
{
  var message = "Hello World!";
  var data = Encrypt(message);
  var res = Decrypt(data);
}

private static RSAParameters GetRSAParameters(string pPublicKey)
{
  byte[] lDer;

  //Set RSAKeyInfo to the public key values. 
  int lBeginStart = "-----BEGIN PUBLIC KEY-----".Length;
  int lEndLenght = "-----END PUBLIC KEY-----".Length;
  string KeyString = pPublicKey.Substring(lBeginStart, (pPublicKey.Length - lBeginStart - lEndLenght));
  lDer = Convert.FromBase64String(KeyString);


  //Create a new instance of the RSAParameters structure.
  RSAParameters lRSAKeyInfo = new RSAParameters();

  lRSAKeyInfo.Modulus = GetModulus(lDer);
  lRSAKeyInfo.Exponent = GetExponent(lDer);

  return lRSAKeyInfo;
}

private static byte[] GetModulus(byte[] pDer)
{
  //Size header is 29 bits
  //The key size modulus is 128 bits, but in hexa string the size is 2 digits => 256 
  string lModulus = BitConverter.ToString(pDer).Replace("-", "").Substring(58, 256);

  return StringHexToByteArray(lModulus);
}

private static byte[] GetExponent(byte[] pDer)
{
  int lExponentLenght = pDer[pDer.Length - 3];
  string lExponent = BitConverter.ToString(pDer).Replace("-", "").Substring((pDer.Length * 2) - lExponentLenght * 2, lExponentLenght * 2);

  return StringHexToByteArray(lExponent);
}

public static byte[] StringHexToByteArray(string hex)
{
  return Enumerable.Range(0, hex.Length)
                   .Where(x => x % 2 == 0)
                   .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                   .ToArray();
}

public static string Encrypt(string mess)
{
  string response = "";
  var input = Encoding.UTF8.GetBytes(mess);
  using (var rsa = new RSACryptoServiceProvider(1024))
  {
    rsa.PersistKeyInCsp = false;
    rsa.ImportParameters(GetRSAParameters(_strPublicKey));
    var decrypt = rsa.Encrypt(input, true);
    response = Convert.ToBase64String(decrypt);
  }
  return response;
}

public static string Decrypt(string mess)
{
  string response = "";
  var input = Convert.FromBase64String(mess);
  using (var rsa = new RSACryptoServiceProvider(2048))
  {
    rsa.PersistKeyInCsp = false;
    rsa.ImportParameters(GetRSAParameters(_strPublicKey));
    var decrypt = rsa.Decrypt(input, false);
    response = Encoding.UTF8.GetString(decrypt);
  }
  return response;
}

上面是我用來加密和解密的代碼。 轉換后,我將它們轉換為字符串,並將其傳遞給解密函數。 請指教

您絕對缺乏閱讀DER的嘗試。 可能是因為您有一個2048位密鑰,而您的“解析器” 充其量僅適用於1024位密鑰(盡管我無法確定它可以合法讀取的密鑰)。

您的公鑰十六進制為

30820122300D06092A864886F70D01010105000382010F003082010A02820101
00B06E6C05B9C7EE05E4AC4C7334E78A123A110C7507E6E53E72B1F9D99D6E5C
2131F0B885A30F11C2BBD91AA8D85E0070C73A8E4301C9B77BADA0D558D2788F
1E37CF5F029393BF4F91E113FE6B516ABD6011C08EAF4FE1807C53DD81A540BC
36BA0548BA5333954051638ADC78DBF7122499FB87273B4E2127A5227EDAC27F
04DEEAAF4769DA7A07A497F8DF6181C1E1457E2247F55851FFFA72F37E34081B
B6E1740E4EB50BABA58761AF763D930422DAAB52CF1791FE821AD1C632BF667E
8C1BD056DA3BBD83CCD82AEB9F69A68C75B4E637E6787F6EE710EC45AB9C16A9
E696979DF2ACC89AEB19CE8BBBED53CCDCC012FB8D22E0C2B9323BC2DA6C2773
790203010001

DER故障(因為我束手無策)是

 30 82 01 22
    30 0D
       06 09 2A 86 48 86 F7 0D 01 01 01
       05 00
    03
       82 01 0F
          00
          30 82 01 0A
             02 82 01 01
                00B06E6C05B9C7EE05E4AC4C7334E78A123A110C7507E6E53E72B1F9D99D6E5C
                2131F0B885A30F11C2BBD91AA8D85E0070C73A8E4301C9B77BADA0D558D2788F
                1E37CF5F029393BF4F91E113FE6B516ABD6011C08EAF4FE1807C53DD81A540BC
                36BA0548BA5333954051638ADC78DBF7122499FB87273B4E2127A5227EDAC27F
                04DEEAAF4769DA7A07A497F8DF6181C1E1457E2247F55851FFFA72F37E34081B
                B6E1740E4EB50BABA58761AF763D930422DAAB52CF1791FE821AD1C632BF667E
                8C1BD056DA3BBD83CCD82AEB9F69A68C75B4E637E6787F6EE710EC45AB9C16A9
                E696979DF2ACC89AEB19CE8BBBED53CCDCC012FB8D22E0C2B9323BC2DA6C2773
                79
             02 03
                010001

相當於ASN.1

SEQUENCE
  SEQUENCE
    OBJECT IDENTIFIER id-rsaEncryption
    NULL
  BIT STRING (0 bits unused) (wrapping)
    SEQUENCE
      INTEGER (positive) 0xB06E...7379
      INTEGER 0x010001

您的模數提取器將跳過29個字節,並讀取下一個128個字節。(為什么這樣做,byte [] => hex => substring => byte []而不是執行new byte[size]並且Buffer.BlockCopy超出了我的范圍)。 問題是,您的密鑰是一個2048位密鑰(模數長度為0x0101,一旦我們刪除了符號填充字節,它的長度為0x0100字節,且設置了高位,所以256 * 8 = 2048位模數)。 因此,您需要讀取256個字節。 而且,更糟糕的是,由於有效載荷比預期的要大,因此它並非以您認為的偏移量開始。 因此,您應該以B0 6E 6C ... 27 73 79結尾(跳過填充字節之后),您以82 01 01 00 *B0 6E 6C ... A5 22 7E結尾(星號標記了所需的開始位置)有效負載)。 因此,這很不好,而且您絕對不會對自己的想法進行加密。 (A5 22 7E序列發生在以36BA開頭的行上,以該行剩下的3個字節結尾)

更糟糕的是GetExponent方法。 似乎嘗試將實際的DER讀數與預設值結合起來。 它應以01 00 01結束,但是它將讀取有效載荷的第一個01作為長度,然后使用該長度從末尾開始計數。 因此,指數值最終僅為01 RSA算法不適用於e=1 ,發生的情況很可能是加密后的自檢確定結果為垃圾,而Win32加密庫得出的結論是,問題是調用者給了它某些東西。與無效鍵的有效句柄相反,它不是有效的鍵句柄。 除了不了解這里的byte [] => hex => substring => byte []模式外,我還不明白為什么這段代碼決定pDer [-3](使用另一種語言的語法)是長度值。 DER只能以“從左到右”的方式讀取,並且如果知道“指數始終為0x010001”,則a)將在pDer [-4]處進行長度編碼的b)僅讀取最后三個字節是可以原諒的,並且c)考慮到該代碼有多少個假設,盲目假設0x010001會更有意義。

因此,您需要a)用正確的解析器或至少一個能以所需的密鑰大小起作用的專用解析器替換解析器,並且b)永遠不要將私鑰用於任何重要的事情,因為您只是將其發布到了Internet(以及私鑰變量甚至沒有在此問題中使用)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM