【问题标题】:Steam RSA encryptionSteam RSA 加密
【发布时间】:2017-02-18 20:18:33
【问题描述】:

我正在开发一个 Steam 网络库,并尝试重建网络登录。它由两个步骤组成: 获取 RSA 密钥并将加密的密码发布到服务器。但大约。因为两个星期我无法让加密工作。

var rsa = new RSACryptoServiceProvider();

var rsaParameters = new RSAParameters {
    Exponent = encryptPasswordModel.PublicKeyExp.HexToByte(),
    Modulus = encryptPasswordModel.PublicKeyMod.HexToByte()
};
rsa.ImportParameters(rsaParameters);
var bytePassword = Encoding.ASCII.GetBytes(encryptPasswordModel.Password);
var encodedPassword = rsa.Encrypt(bytePassword, false);
return Convert.ToBase64String(encodedPassword);

这工作正常,但我相信 Steam rsa 加密的实施在某些时候发生了变化。目前可以在here找到加密。 Steam 还使用了一个名为 jsbn.js 的包。可以找到here

encrypt: function($data, $pubkey) {
  if (!$pubkey) return false;
  $data = this.pkcs1pad2($data, ($pubkey.modulus.bitLength() + 7) >> 3);
  if (!$data) return false;
  $data = $data.modPowInt($pubkey.encryptionExponent, $pubkey.modulus);
  if (!$data) return false;
  $data = $data.toString(16);
  if (($data.length & 1) == 1)
    $data = "0" + $data;
  return Base64.encode(Hex.decode($data));
}

pkcs1pad2: function($data, $keysize) {
  if ($keysize < $data.length + 11)
    return null;
  var $buffer = [];
  var $i = $data.length - 1;
  while ($i >= 0 && $keysize > 0)
    $buffer[--$keysize] = $data.charCodeAt($i--);
  $buffer[--$keysize] = 0;
  while ($keysize > 2)
    $buffer[--$keysize] = Math.floor(Math.random() * 254) + 1;
  $buffer[--$keysize] = 2;
  $buffer[--$keysize] = 0;
  return new BigInteger($buffer);
}

正如我们所见,我们有一个类似于自定义加密填充的东西,称为“pkcs1pad2”。我怎样才能在 C# 中以相同的方式实现这一点而没有那么多麻烦(最好的解决方案是 .net 核心解决方案,但它不是必需的)。

我已经用RSA.Create(); 尝试过,但还没有成功。

var rsaParameters = new RSAParameters {
    Exponent = encryptPasswordModel.PublicKeyExp.HexToByte(),
    Modulus = encryptPasswordModel.PublicKeyMod.HexToByte()
};
var rsa2 = RSA.Create();
rsa2.ImportParameters(rsaParameters);
var byteEncodedPassword = rsa2.Encrypt(Encoding.ASCII.GetBytes(encryptPasswordModel.Password), RSAEncryptionPadding.Pkcs1);
var encryptedPassword = Convert.ToBase64String(byteEncodedPassword);

我认为这还没有解决,因为填充,但我如何能够扩展 RSAEncryptionPadding 的算法。

【问题讨论】:

    标签: c# encryption cryptography rsa steam


    【解决方案1】:

    pkcs1pad2 看起来它构建了以下数据(从后到前):

    0x00 0x02 [a series of non-zero random bytes] 0x00 [data]
    

    这正是 PKCS#1 v1.5 加密填充算法 (https://www.rfc-editor.org/rfc/rfc3447#section-7.2.1),这是 .NET 调用的 RSAEncryptionPadding.Pkcs1(当将 false 传递给 fOAEP 时,您从 RSACryptoServiceProvider.Encrypt 得到)。

    如果事情突然停止工作,这确实表明其中之一

    • 使用的密钥已更改。
    • 您发送的密码已更改。

    有一个额外的候选人

    • 加密前您应该对密码执行的操作已更改。

    关于扩展 RSAEncryptionPadding

    .NET 中的类型实际上并不执行 RSA,它们遵循可以为它们执行 RSA 的系统库,其中包括填充。所以它不是一个多态结构,你可以创建一个新的并传递。如果您想制作自己的填充,则需要定义自己的 RSA 子类,然后对填充选项进行非标准添加。

    又是一项繁重的工作,很难安全地完成(RSA 解密中的时序问题),您应该很高兴您不需要这样做,因为填充算法不是您的问题有。

    【讨论】:

    • 使用的关键是每小时都在变化。我正在相应地更新它(我总是仔细检查)。密码也没有改变。我找到了另一个使用 RSA 加密的示例,您现在可以找到 here
    猜你喜欢
    • 2015-03-16
    • 1970-01-01
    • 2015-02-27
    • 2012-03-13
    • 2013-07-15
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多