2012-06-11 26 views
3

美好的一天。WinAPI - > CryptoAPI - > RSA,與私人加密,與公衆解密

我需要教Windows CryptoAPI使用私鑰(不公開)部分密鑰對消息進行加密,並用public解密。這對於給用戶提供信息是必要的,他們可以閱讀,但無法更改。

怎麼現在的工作:

我得到的情況下

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) 

感謝您的關注/幫助。

更新

是的,我可以用一個數字簽名等metods ...

的問題是,我需要加密一個數據庫字段,並確保沒有人,但我可以改變它。只有在我的程序的幫助下才能閱讀這個字段(直到有人反編譯並獲得公鑰)。這可以通過對稱密鑰和數字簽名來完成,但是接下來我需要創建另一個字段並存儲另一個密鑰等等......

我確實希望我們能夠以某種方式教WIN API執行我想要的操作。我知道我可以用RSA來實現,我希望WinAPI支持這個功能。

回答

2

不支持使用私鑰加密數據並使用公鑰解密數據,因爲任何使用「發佈」公鑰的人都可以解密它。那麼加密它的價值是什麼?

如果您想驗證數據未被更改,您將需要改爲簽名數據。簽名使用私鑰加密數據的散列。看看簽名功能。

你也許可以欺騙簽名功能來做你想做的事情。我已經用其他實現完成了這項工作,但我沒有使用Microsoft CryptoAPI進行嘗試。

此外,請注意,使用RSA加密,純文本消息不能超過密鑰。因此,如果您使用的是2048位密鑰,則只能加密最多256個字節的消息體(減少一些開銷)。

考慮使用非對稱加密只是爲了傳遞對稱密鑰,並使用對稱密鑰來加密和解密任何大小的數據。

更新

您可以使用CryptSignHash()功能這一點。通常情況下,這是用來「簽到」的哈希,但你可以把你想成散列的任何數據:

使用的 在CryptSetHashParam的dwParam參數HP_HASHVAL值設置在哈希對象的哈希值。

如果希望輸入是SHA1哈希值,那麼您可能會被限制爲很多字節。

或者,您可能希望考慮使用OpenSSL。如果我沒有記錯,那麼使用它的RSA signing函數用私鑰進行加密是非常簡單的。

此外,我使用SecureBlackbox的舊版(免費版)完成了同樣的事情。您可能能夠找到舊的免費版本,但它不是Unicode友好的,所以如果您使用新的Delphi,則需要進行一些轉換。我過去也這樣做過,所以這並不難。

您也可以考慮嘗試使用當前的SecureBlackbox,並在適用的情況下購買它。

否則,如您所述,請對其進行簽名以檢測篡改,並使用只有程序知道才能對其進行混淆的對稱密鑰對其進行加密。

如果他們破解你的代碼,反正任何事情都是公平的。

+0

tnx爲好的答案,請看看更新 – TheHorse

+0

@TheHorse,我更新了我的答案與一些更多的信息。 –

3

嚴格地說,當「簽約」消息:

  • 用私鑰人解密哈希他們私人關鍵。
  • 然後他們發送「解密」散列連同消息。
  • 接收器,然後加密用公鑰

如果「加密」哈希原始消息的哈希值相匹配的簽名,你就知道該消息沒有被改變,並且被髮送有私鑰的人。以下僞代碼表示簽名算法:

//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); 

可以使用此相同的機制來完成您想要的操作。除非你不關心哈希,你只是想對數據進行加密的一些(小)量:

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

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

我將離開CryptoAPI電話作爲鍛鍊; Tibial - 因爲我還在努力圖微軟的Crypto API。