生成具有大公共指数的RSA密钥

huangapple go评论78阅读模式
英文:

Generate RSA key with large public exponent

问题

步骤1: 我分别为Alice和Bob生成了RSA密钥对,并使用Alice的公钥加密了一条消息。

步骤2: 我将Bob的公钥的公共指数与Alice的私钥的私有指数相乘,得到一个新的数字。

步骤3: 我通过keyRegen := rsa.PublicKey{N: keyPubAliceN, E: ENew}生成了一个新的RSA公钥,并用它来加密步骤1中加密的消息。

步骤4: 我使用Bob的私钥解密了步骤3中重新加密的消息。理论上,Bob现在可以得到原始消息,这是预期的输出。

问题: 然而,我发现rsa.PublicKey中的公共指数应该是一个int,而我在步骤2中生成的新的公共指数是一个big.Int。我将其转换为int并使用新生成的公钥进行加密,但出现了错误panic: crypto/rsa: public exponent too small。而且我猜想我不应该进行这样的转换,因为新的数字可能大于int的范围。那么有没有办法生成具有大公共指数的新RSA密钥?谢谢!

代码:

package main
import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"fmt"
	"math/big"
)

func main() {
	keyPriAlice, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
		panic(err)
	}
	keyPubAlice := keyPriAlice.PublicKey
	keyPriAliceD := keyPriAlice.D
	keyPubAliceN := keyPubAlice.N

    keyPriBob, err := rsa.GenerateKey(rand.Reader, 1024)
    if err != nil {
    	panic(err)
    }
    keyPubBob := keyPriBob.PublicKey
    keyPubBobE := big.NewInt(int64(keyPubBob.E))
    
    message := "secret"
    encryptedBytes, err := rsa.EncryptOAEP(
    	sha256.New(),
    	rand.Reader,
    	&keyPubAlice,
    	[]byte(message),
    	nil)
    if err != nil {
    	panic(err)
    }
    
    z := new(big.Int)
    y := z.Mul(keyPriAliceD, keyPubBobE)
    ENew := int(y.Int64())
    keyRegen := rsa.PublicKey{N: keyPubAliceN, E: ENew}
    
    reEncryptedBytes, err := rsa.EncryptOAEP(
    	sha256.New(),
    	rand.Reader,
    	&keyRegen,
    	[]byte(encryptedBytes),
    	nil)
    if err != nil {
    	panic(err)
    }
    
    // 使用Bob的私钥解密重新加密的明文
    decryptedBytes, err := keyPriBob.Decrypt(nil, reEncryptedBytes, &rsa.OAEPOptions{Hash: crypto.SHA256})
    fmt.Println("decryptedBytes:", decryptedBytes)
}
英文:

Step 1. I generated RSA key pairs for Alice and Bob, respectively, and encrypted a message for Alice using Alice's public key.

Step 2. I multiplied the public exponent of Bob's public key with the private exponent of Alice's private key to have a new number.

Step 3. I generated a new RSA public key by keyRegen := rsa.PublicKey{N: keyPubAliceN, E: ENew} and used it to encrypt the message encrypted in step 1.

Step 4. I decrypted the re-encrypted message from step 3 using Bob's private key. Theoretical now Bob can get the original message, which is the expected output.

Problem: However, I found that the public exponent in rsa.PublicKey should be an int, while my new public exponent generated in step 2 is a big.Int. I converted it into int and used the newly generated public key to do the encryption but error panic: crypto/rsa: public exponent too small happened. Also I guess I should not do such a conversion because the new number is probably larger than int range. Then are there any ways to generate a new RSA key with the large public exponent? Thank you!

Codes:

package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"fmt"
"math/big"
)
func main() {
keyPriAlice, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
keyPubAlice := keyPriAlice.PublicKey
keyPriAliceD := keyPriAlice.D
keyPubAliceN := keyPubAlice.N
keyPriBob, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
keyPubBob := keyPriBob.PublicKey
keyPubBobE := big.NewInt(int64(keyPubBob.E))
message := "secret"
encryptedBytes, err := rsa.EncryptOAEP(
sha256.New(),
rand.Reader,
&keyPubAlice,
[]byte(message),
nil)
if err != nil {
panic(err)
}
z := new(big.Int)
y := z.Mul(keyPriAliceD, keyPubBobE)
ENew := int(y.Int64())
keyRegen := rsa.PublicKey{N: keyPubAliceN, E: ENew}
reEncryptedBytes, err := rsa.EncryptOAEP(
sha256.New(),
rand.Reader,
&keyRegen,
[]byte(encryptedBytes),
nil)
if err != nil {
panic(err)
}
// decrypt the re-encrypted plaintext using Bob's private key
decryptedBytes, err := keyPriBob.Decrypt(nil, reEncryptedBytes, &rsa.OAEPOptions{Hash: crypto.SHA256})
fmt.Println("decryptedBytes:", decryptedBytes)
}

答案1

得分: 0

你可能需要使用不同的库来完成这个任务。在大多数现代RSA环境中,出于安全原因,我们希望私钥指数d很大,但出于性能原因,我们希望公钥指数e很小。实际上,我见过的绝大多数安全实现选择了65537作为e,这是安全且快速的选择(因为它只包含两个1)。

Go库做出了一个假设,即几乎所有不是恶意攻击的真实场景都希望e很小,因此e可以适应int类型,这可能有些不慎重,但最终是合理的。你可能会发现OpenSSL更适合这个目的,因为它对传递给它的数据做出的假设较少。

英文:

You'll probably need to use a different library for this. In most modern RSA contexts, we want d, the private exponent, to be large for security reasons, but we want e to be small for performance reasons. As a practical matter, the vast majority of secure implementations I've seen choose 65537 for e, which is secure and fast (due to containing exactly two ones).

The Go library has made the assumption, based on the fact that practically every real-world scenario that isn't an exploit wants a small e, that e will fit into an int, which may have been improvident, but is ultimately reasonable. You may find that OpenSSL is more suitable for this purpose, since it tends to make fewer assumptions about the data passed to it.

huangapple
  • 本文由 发表于 2022年4月29日 16:43:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/72055191.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定