Created
July 23, 2018 07:01
-
-
Save dimchansky/2d7709c77517b28cdcd8d20a5b1188a3 to your computer and use it in GitHub Desktop.
Chosen Ciphertext Attack against RSA
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/rand" | |
"crypto/rsa" | |
"fmt" | |
"math/big" | |
"os" | |
) | |
func main() { | |
const size = 128 // using small key size for simplicity, but it works for any key size | |
// victim generates RSA keys | |
priv, err := rsa.GenerateKey(rand.Reader, size) | |
if err != nil { | |
fmt.Printf("GenerateKey: %v\n", err) | |
os.Exit(1) | |
} | |
pub := &priv.PublicKey | |
// message to encrypt | |
m := big.NewInt(42) | |
fmt.Printf("message: %v\n", m) | |
// victim encrypts the message | |
me := encrypt(pub, m) | |
fmt.Printf("encrypted message: %v\n", me) | |
// victim tests message decryption | |
md := decrypt(priv, me) | |
fmt.Printf("test decryption: %v\n", md) | |
// hacker listening in on victim's communications, manages to collect a ciphertext message. | |
// hacker wants to be able to read the message, to recover message he computes evil message | |
evMsg, t := prepareEvilMessage(pub, me) | |
fmt.Printf("evil message: %v\n", evMsg) | |
// hacker gets victim to sign evMsg with victim's private key, thereby decrypting evMsg. | |
// victim has never seen evMsg before, victim signs the message and send it back to hacker: | |
u := decrypt(priv, evMsg) // victim has to sign the message, not the hash of the message | |
fmt.Printf("signed evil message: %v\n", u) | |
// hacker decrypts the message | |
c := new(big.Int).Mod(new(big.Int).Mul(t, u), pub.N) | |
fmt.Printf("hacked message: %v\n", c) | |
// Moral: Never use RSA to sign a random document presented to you by a | |
// stranger. Always use a one-way hash function first. | |
} | |
func prepareEvilMessage(pub *rsa.PublicKey, m *big.Int) (*big.Int, *big.Int) { | |
r, _ := rand.Int(rand.Reader, pub.N) | |
t := new(big.Int).ModInverse(r, pub.N) | |
x := encrypt(pub, r) | |
evMsg := new(big.Int).Mod(new(big.Int).Mul(x, m), pub.N) | |
return evMsg, t | |
} | |
func encrypt(pub *rsa.PublicKey, m *big.Int) *big.Int { | |
return new(big.Int).Exp(m, big.NewInt(int64(pub.E)), pub.N) | |
} | |
func decrypt(priv *rsa.PrivateKey, m *big.Int) *big.Int { | |
return new(big.Int).Exp(m, priv.D, priv.N) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Play with it