-1

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 :)

Leo
  • 65
  • 2
  • 10
  • 3
    Encryption paddings are intentionally non-deterministic for security reasons, s. [RFC 8017](https://datatracker.ietf.org/doc/html/rfc8017) – Topaco Apr 26 '22 at 16:11
  • 1
    "I want the same result for the same message every time when I do the RSA encryption" Could you explain the rational behind this wish? Because the natural, sensible and secure answer would be "No you don't!". – Volker Apr 26 '22 at 16:27

1 Answers1

3

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.

Playground

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Thank you @Rob Napier. Actually I want to use encryption in blockchain smart contract (using Hyperledger Fabric) and I found that the randomness of the encryption algorithms made the smart contract fail because different peers in the blockchain network execute the smart contract and the outputs should be deterministic. That's why I want to do deterministic RSA. If it's so serious maybe I should have another question about how to do such encryption with randomness in Hyperledger Fabric smart contract then. – Leo Apr 27 '22 at 01:41
  • No, do not do that. I'm not particularly familiar with Hyperledger Fabric, but the answer will boil down to what attributes you're trying to achieve in terms of your cryptography. You should find a standard tool for achieving that. Do not invent novel crypto-formats. Very small changes can completely break their security. I would never consider creating a smart contract system without an expert involved (on the assumption the contracts are important in any way). – Rob Napier Apr 27 '22 at 13:35
  • If you're interested in studying this field yourself, it is difficult but absolutely something you can learn. I always recommend folks start with Dan Boneh's course. It's a very hard class, but well worth it. https://www.coursera.org/learn/crypto – Rob Napier Apr 27 '22 at 13:41