在 C Sharp 中使用 RSA 对 128 字节的字节数组进行签名
我对密码学完全陌生,我需要使用我用 C Sharp 生成的 RSA 密钥对 128 字节的字节数组进行签名。密钥必须是 1024 位。
我发现了一些如何将 RSA 与 C Sharp 一起使用的示例,我当前尝试使用的代码是:
public static void AssignParameter()
{
const int PROVIDER_RSA_FULL = 1;
const string CONTAINER_NAME = "SpiderContainer";
CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.KeyContainerName = CONTAINER_NAME;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
rsa = new RSACryptoServiceProvider(cspParams);
rsa.KeySize = 1024;
}
public static string EncryptData(string data2Encrypt)
{
AssignParameter();
StreamReader reader = new StreamReader(path + "publickey.xml");
string publicOnlyKeyXML = reader.ReadToEnd();
rsa.FromXmlString(publicOnlyKeyXML);
reader.Close();
//read plaintext, encrypt it to ciphertext
byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(data2Encrypt);
byte[] cipherbytes = rsa.Encrypt(plainbytes, false);
return Convert.ToBase64String(cipherbytes);
}
此代码适用于小字符串(因此短字节数组),但是当我尝试使用 128 的字符串时我收到一条错误消息: CryptographicException 未处理:长度错误 (好吧,它可能不准确地说“长度错误”,我得到丹麦语的错误,那就是“Forkert længde”,它直接翻译为“长度错误”)。
谁能告诉我如何使用 C Sharp 中的 1024 位 RSA 密钥加密 128 字节的字节数组?
提前致谢, LordJesus
编辑:
好的,只是为了澄清一下:我有一条消息,我使用 SHA-256 从中进行哈希处理。这给出了一个 32 字节的数组。该数组使用自定义填充进行填充,因此最终成为 128 字节数组。然后应该使用我的私钥对这个填充的哈希进行签名,以便接收者可以使用我的公钥来验证收到的消息与发送的消息是否相同。这可以用 1024 位的密钥来完成吗?
I am completely new to cryptography and I need to sign a byte array of 128 bytes with an RSA key i have generated with C sharp. The key must be 1024 bits.
I have found a few examples of how to use RSA with C sharp and the code I'm currently trying to use is:
public static void AssignParameter()
{
const int PROVIDER_RSA_FULL = 1;
const string CONTAINER_NAME = "SpiderContainer";
CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.KeyContainerName = CONTAINER_NAME;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
rsa = new RSACryptoServiceProvider(cspParams);
rsa.KeySize = 1024;
}
public static string EncryptData(string data2Encrypt)
{
AssignParameter();
StreamReader reader = new StreamReader(path + "publickey.xml");
string publicOnlyKeyXML = reader.ReadToEnd();
rsa.FromXmlString(publicOnlyKeyXML);
reader.Close();
//read plaintext, encrypt it to ciphertext
byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(data2Encrypt);
byte[] cipherbytes = rsa.Encrypt(plainbytes, false);
return Convert.ToBase64String(cipherbytes);
}
This code works fine with small strings (and thus short byte arrays) but when I try this with a string of 128 characters I get an error saying:
CryptographicException was unhandled: Wrong length
(OK, it might not precisely say 'Wrong length', I get the error in danish, and that is 'Forkert længde' which directly translates to 'Wrong length').
Can anyone tell me how I can encrypt a byte array of 128 bytes with a RSA key of 1024 bits in C sharp?
Thanks in advance,
LordJesus
EDIT:
Ok, just to clarify things a bit: I have a message, from which i make a hash using SHA-256. This gives a 32 byte array. This array is padded using a custom padding, so it ends up being a 128 byte array. This padded hash should then be signed with my private key, so the receiver can use my public key to verify that the message received is the same as the message sent. Can this be done with a key of 1024 bits?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果您想签名,您就不想加密。签名和加密是不同的算法。更糟糕的是,有一种著名的签名算法称为 RSA,还有一种著名的非对称加密算法也称为 RSA,并且该签名算法最初提出(并且仍然在许多地方)为“您使用私钥”。这简直令人困惑。
在 RSA 加密中,要加密的数据(使用公钥)必须用 填充PKCS#1(RSA 标准)将其描述为“Type 2 padding”,然后将结果(其长度与模数相同)通过 RSA 核心的模幂运算进行处理(在核心,但 RSA 不仅仅是模幂;填充对于安全性非常重要)。
签名时,必须对要签名的数据进行哈希处理,然后将哈希值嵌入到描述刚刚使用的哈希函数的结构中,并且编码的结构本身用“类型 1 填充”进行填充——不是相同的填充比加密的填充更重要,这也很重要。
无论哪种方式,普通的 RSA 引擎都会自行执行类型 1 或类型 2 填充,并且大多数 RSA 签名引擎也会自行处理标识所使用的哈希函数的结构。 RSA 签名引擎(例如
RSACryptoServiceProvider
)可以与SignHash()
配合使用,后者需要哈希值(从 SHA-256 获取的 32 字节,没有) em> 任何类型的封装结构或类型 1 填充 -RSACryptoServiceProvider
自行处理),或SignData()
,它期望数据被签名(然后引擎也会进行哈希计算)。总而言之,如果你自己做了任何类型的填充,那么你就做错了。如果您使用
Encrypt()
来计算签名,那么您也做错了。If you want to sign you do not want to encrypt. Signatures and encryption are distinct algorithms. It does not help that there is a well-known signature algorithm called RSA, and a well-known asymmetric encryption algorithm also called RSA, and that the signature algorithm was first presented (and still is in many places) as "you encrypt with the private key". This is just plain confusing.
In RSA encryption, the data to encrypt (with the public key) must be padded with what PKCS#1 (the RSA standard) describes as "Type 2 padding", and the result (which has the same length than the modulus) is then processed through the modular exponentiation which is at the core of RSA (at the core, but RSA is not only a modular exponentiation; the padding is very important for security).
When signing, the data to sign must be hashed, then the hash value is embedded in a structure which describes the hash function which was just used, and the encoded structure is itself padded with a "Type 1 padding" -- not the same padding than the padding for encryption, and that's important, too.
Either way, a normal RSA engine will perform the type 1 or type 2 padding itself, and most RSA signature engines will also handle themselves the structure which identifies the used hash function. A RSA signature engine such as
RSACryptoServiceProvider
can work either withSignHash()
, which expects the hash value (the 32 bytes obtained from SHA-256, without any kind of encapsulating structure or type 1 padding --RSACryptoServiceProvider
handles that itself), orSignData()
, which expects the data to be signed (the engine then does the hash computation too).To sum up, if you do any kind of padding yourself, then you are doing it wrong. If you used
Encrypt()
to compute a signature, then you are doing it wrong, too.当您在 OAEP 关闭的情况下调用
Encrypt
时,加密 128 字节的最小密钥大小将为 1112 位。请注意,像rsa.KeySize = 1024
这样设置密钥大小不会有帮助,您需要实际生成正确大小的密钥并使用它们。这对我有用:
但是请注意,我没有使用加密容器,因此,我不需要您的
AssignParameter
,但如果您需要使用它,修改代码应该足够容易。如果您需要加密大量数据(远大于 128 字节)本文 提供了有关如何执行此操作的示例代码。
The minimum key size for encrypting 128 bytes would be 1112 bits, when you are calling
Encrypt
with OAEP off. Note that setting the key size like thisrsa.KeySize = 1024
won't help, you need to actually generate they key of the right size and use them.This is what worked for me:
Note however, that I'm not using a crypto container, and thus, I don't need your
AssignParameter
, but if you need to use it, modifying the code should be easy enough.If you ever need to encrypt large quantities of data (much larger than 128 bytes) this article has sample code on how to do this.
显然,根据这个问题 - 如何使用C# 中的 RSA 加密文件(大数据) - RSA 只能加密短于其密钥长度的数据。
奇怪的。 `RSACryptoServiceProvider.Encrypt() 的 MSDN 文档 表示如果 rgb 参数的长度大于允许的最大长度,则可能会抛出 CryptographicException。
好吧。这看起来很奇怪,特别是因为关于所述最大值的文档似乎没有太多。
进一步挖掘一下,在备注下有这样的内容:
如果您运行的是 XP 或更高版本,并且使用 OAEP 填充,则限制为
<块引用>
模数大小 -2 -2*hLen,其中 hLen 是哈希的大小
不知道“散列的大小”可能是多少,因为文档,AFAICS,除了数字签名之外,没有在任何地方提到“散列”。
如果您运行的是 Windows 2000 或更高版本,并且安装了“高加密包”(同样,不知道您是如何发现这一点的),则该限制规定为
<块引用>
模数大小 - 11。(11 字节是可能的最小填充。)
否则(Windows 98、Millenium 或 Windows 2000 或更高版本,没有上述“高加密包”,那么您会得到“不支持直接加密和 OAEP 填充”,限制在哪里
<块引用>
对称密钥允许的最大大小。
说...等一下...RSA 是一种非对称算法,对吗?
无价值的文档。谢什。
Apparently, according to this question — how to use RSA to encrypt files (huge data) in C# — RSA can only encrypt data shorter than its key length.
Bizarre. The MSDN docs for`RSACryptoServiceProvider.Encrypt() say that a CryptographicException may be thrown if the length of the rgb parameter is greater than the maximum allowed length.
Well. That seems odd, especially since there doesn't seem to be much in the way of documentation regarding said maximum.
A little further digging, under Remarks has this:
If you are running XP or later and you're using OAEP padding, then the limit is stated to be
No idea what the "size of the hash" might be, since the docs, AFAICS, don't mention "hash" anywhere except in regards to digital signatures.
If you are running Windows 2000 or later with the "high encryption pack" installed (again, no idea how you find that out), then the limit is stated to be
Otherwise (Windows 98, Millenium or Windows 2000 or later without the aforementioned "high encryption pack" then you get "Direct Encryption and OAEP padding not supported", where the limitation is
Say...wait a second... RSA is an asymmetric algorithm, right?
Worthless documentation. Sheesh.
请参阅 http://msdn.microsoft.com/ en-us/library/system.security.cryptography.rsacryptoserviceprovider.encrypt.aspx。抛出的异常可能是“rgb参数的长度大于允许的最大长度”。
See http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.encrypt.aspx. The exception thrown is probably "The length of the rgb parameter is greater than the maximum allowed length."
通常RSA加密有填充,并且由于您的加密数据大小达到密钥大小,因此没有填充空间。尝试使用较长的密钥或较小的数据大小进行加密。
Usually RSA encryption has padding, and since your encrypted data size goes to the key size, there is no space for padding. Try to use longer key or less data size to encrypt.
您真的需要自定义填充吗?如果没有,您可以使用 RSACryptoServiceProvider.SignData 方法< /a>
Do you real need the custom padding? If not you could just use RSACryptoServiceProvider.SignData Method