In the code below (also at http://play.golang.org/p/77fRvrDa4A but takes "too long to process" in the browser there) the 124 byte version of the sourceText won't encrypt because: "message too long for RSA public key size" of 1024. It, and the longer 124 byte sourceText version, work with 2048 bit key size.
My question is how does one exactly calculate the key size in rsa.GenerateKey given the byte length of the source text? (A small paragraph size of text takes nearly 10 seconds at 4096 key size, and I don't know the length of the sourceText until runtime.)
There's a very brief discussion of this at https://stackoverflow.com/a/11750658/3691075, but it's not clear to me as I'm not a crypto guy.
My goal is to encrypt, store in a DB and decrypt about 300-byte long JSON strings. I control both the sending and the receiving end. Text is encrypted once, and decrypted many times. Any hints of strategy would be appreciated.
package main
import (
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"fmt"
"hash"
"log"
"time"
)
func main() {
startingTime := time.Now()
var err error
var privateKey *rsa.PrivateKey
var publicKey *rsa.PublicKey
var sourceText, encryptedText, decryptedText, label []byte
// SHORT TEXT 92 bytes
sourceText = []byte(`{347,7,3,8,7,0,7,5,6,4,1,6,5,6,7,3,7,7,7,6,5,3,5,3,3,5,4,3,2,10,3,7,5,6,65,350914,760415,33}`)
fmt.Printf("
sourceText byte length:
%d
", len(sourceText))
// LONGER TEXT 124 bytes
// sourceText = []byte(`{347,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,65,350914,760415,33}`)
// fmt.Printf("
sourceText byte length:
%d
", len(sourceText))
if privateKey, err = rsa.GenerateKey(rand.Reader, 1024); err != nil {
log.Fatal(err)
}
// fmt.Printf("
privateKey:
%s
", privateKey)
privateKey.Precompute()
if err = privateKey.Validate(); err != nil {
log.Fatal(err)
}
publicKey = &privateKey.PublicKey
encryptedText = encrypt(publicKey, sourceText, label)
decryptedText = decrypt(privateKey, encryptedText, label)
fmt.Printf("
sourceText:
%s
", string(sourceText))
fmt.Printf("
encryptedText:
%x
", encryptedText)
fmt.Printf("
decryptedText:
%s
", decryptedText)
fmt.Printf("
Done in %v.
", time.Now().Sub(startingTime))
}
func encrypt(publicKey *rsa.PublicKey, sourceText, label []byte) (encryptedText []byte) {
var err error
var md5_hash hash.Hash
md5_hash = md5.New()
if encryptedText, err = rsa.EncryptOAEP(md5_hash, rand.Reader, publicKey, sourceText, label); err != nil {
log.Fatal(err)
}
return
}
func decrypt(privateKey *rsa.PrivateKey, encryptedText, label []byte) (decryptedText []byte) {
var err error
var md5_hash hash.Hash
md5_hash = md5.New()
if decryptedText, err = rsa.DecryptOAEP(md5_hash, rand.Reader, privateKey, encryptedText, label); err != nil {
log.Fatal(err)
}
return
}