4

再会。

我需要教 Windows CryptoAPI 使用密钥的私有(非公共)部分加密消息,并使用公共解密。这是向用户提供他们可以阅读但不能更改的信息所必需的。

现在如何运作:

我得到了上下文

CryptAcquireContext(@Prov, PAnsiChar(containerName), nil, PROV_RSA_FULL, 0)

生成密钥对

CryptGenKey(Prov, CALG_RSA_KEYX, CRYPT_EXPORTABLE, @key)

加密(问题就在这里。“密钥” - 一个密钥对,该函数使用它的公共部分);

CryptEncrypt(key, 0, true, 0, @res[1], @strLen, buffSize)

解密(同样的问题,它使用密钥的私有部分)

CryptDecrypt(key, 0, true, 0, @res[1], @buffSize)

感谢您的关注/帮助。

更新

是的,我可以使用数字签名和其他方法...

问题是我需要加密一个数据库字段并确保除了我之外没有人可以更改它。只有在我的程序的帮助下才能读取这个字段(直到有人反编译它并获得公钥)。这可以通过对称密钥和数字签名来完成,但是我需要创建另一个字段并存储另一个密钥等等......

我确实希望我们能以某种方式教 WIN API 做我想做的事。我知道我可以用 RSA 做到这一点,我希望 WinAPI 能以某种方式支持这个功能。

4

2 回答 2

3

Strictly speaking, when "signing" a message:

  • the person with the private key decrypts the hash with their private key.
  • they then send that "decrypted" hash along with the message.
  • the receiver then encrypts the signature with the public key

If the "encrypted" hash matches the hash of the original message, you know the message has not been altered, and was sent by the person with the private key. The following pseudo-code represents the signing algorithm:

//Person with private key generating message and signature
originalHash = GenerateHashOfMessage(message);
signature = RsaDecrypt(originalHash, privateKey);

//Receiver validating signed message
hash = GenerateHashOfMessage(message);
originalHash = RsaEncrypt(signature, publicKey);
messageValid = (hash == originalHash);

This same mechanism can be used to accomplish what you want. Except you don't care about hashes, you just want to encrypt some (small) amount of data:

//Person with private key
cipherText = RsaDecrypt(plainText, privateKey);

//Person with public key
plainText = RsaEncrypt(cipherText, publicKey);

i'll leave the CryptoAPI calls as an excercise - since i'm still trying to figure out Microsoft's Crypto API.

于 2012-10-17T23:42:49.897 回答
2

不支持使用私钥加密数据并使用公钥解密数据,因为任何拥有“已发布”公钥的人都可以解密它。那么加密它有什么价值呢?

If you want to verify that data hasn't been changed, you will want to sign the data instead. Signing encrypts a hash of the data with the private key. Look at the signing functions.

You may be able to trick out the signing functions to do what you want. I've done this with other implementations, but I haven't tried with the Microsoft CryptoAPI.

Also, note that with RSA encryption, the plain text message cannot be longer than the key. So, if you are using a 2048 bit key, you can only encrypt a message body of up to 256 bytes (minus a few for overhead).

Consider using asymmetric encryption just to pass a symmetric key, and use the symmetric key to encrypt and decrypt any size data.

Update

You may be able to use the CryptSignHash() function for this. Normally, this is used to "sign" a hash, but you can put any data you want into the hash:

Set the hash value in the hash object by using the HP_HASHVAL value of the dwParam parameter in CryptSetHashParam.

You might be limited to so many bytes if the input is expected to be a SHA1 hash value.

Alternatively, you may wish to consider using OpenSSL. If I recall correctly, it's pretty straight forward to use its RSA signing functions to encrypt with the private key.

Also, I accomplished the same thing using the old (freeware) version of SecureBlackbox. You may be able to find the old free version, but it's not Unicode friendly, so you'll have some conversion to do if you're using a new Delphi. I've done this in the past also, so it's not too difficult.

You may also consider trying out the current SecureBlackbox and purchase it if it works for you.

Otherwise, as you stated, sign it to detect tampering, and encrypt it with a symmetric key that only the program knows in order to obfuscate it.

If they crack your code, anything's fair game anyway.

于 2012-06-11T20:09:20.677 回答