'Deterministic RSA encryption in Golang - how to get same result for a given message under mutiple times of encryption
For the codes below of RSA encryption, every time when I do the encryption for the same message, the result would be different. I found that this is due to the rand.Reader in the rsa.EncryptOAEP function to make it more secure according to the doc. But I want the same result for the same message every time when I do the RSA encryption. How to do so using Golang? There is a similar question but it seems that answers are not about how to achieve this. Thank you!
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
)
func main() {
privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
publicKey := privateKey.PublicKey
message := "super secret message"
encryptedBytes, err := rsa.EncryptOAEP(
sha256.New(),
rand.Reader,
&publicKey,
[]byte(message),
nil)
if err != nil {
panic(err)
}
fmt.Println("encrypted bytes: ", encryptedBytes)
}
Update: I want to do deterministic RSA because I want deterministic encryption results when using Hyperledger Fabric chaincode (blockchain smart contract) which requires deterministic outputs. Thank you all for the warnings. Then I guess I should focus on how to enable these encryption algorithms in chaincode. Relevant question for later comers' information if it helps :)
Solution 1:[1]
This approach, as you've read, breaks very important security features of the algorithm, and must never be used to secure live systems of any kind. However, for the purposes of certain kinds of testing and development, it can be useful. I will assume that this is what you mean to do with it.
The key is that rsa.EncryptOAEP accepts an arbitrary io.Reader for its entropy. It does not require this to be a rand.Reader. If you do not care about the security of the system, it can be whatever you like. For example, you could build a "zero reader" that just returns zeros forever:
type zeroReader struct{}
func (z zeroReader) Read(p []byte) (n int, err error) {
for i, _ := range p {
p[i] = 0
}
n = len(p)
return
}
With that, you can pass zeroReader{} as your entropy:
// !!! The security of this call is completely broken !!!
// !!! It must never be used on live data !!!
encryptedBytes, err := rsa.EncryptOAEP(
sha256.New(),
zeroReader{}, // !!! I am intentionally breaking the security here !!!
&publicKey,
[]byte(message),
nil)
If you do mean to use this for any kind of live data, then you must redesign your system to not require this. As in the case of the question you link, often people try to do this because they misunderstand RSA. Don't do that.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Rob Napier |
