生成具有大 public 指数的 RSA 密钥

Generate RSA key with large public exponent

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

第 2 步。 我将 Bob 的 public 密钥的 public 指数与 Alice 私钥的私有指数相乘得到一个新数字。

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

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

问题: 但是,我发现 rsa.PublicKey 中的 public 指数应该是 int,而我的新 [=43] =] 第二步生成的指数是一个big.Int。我将其转换为 int 并使用新生成的 public 密钥进行加密,但发生错误 panic: crypto/rsa: public exponent too small。另外我想我不应该做这样的转换,因为新数字可能大于 int 范围。那么有什么方法可以生成具有大 public 指数的新 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)
    }
    
    // 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)
    }

您可能需要为此使用不同的库。在大多数现代 RSA 上下文中,出于安全原因,我们希望私有指数 d 较大,但出于性能原因,我们希望 e 较小。实际上,我见过的绝大多数安全实现都为 e 选择 65537,它既安全又快速(因为恰好包含两个)。

Go 库做出了这样的假设,基于这样一个事实,即几乎每个 real-world 不是漏洞利用的场景都需要一个小的 e,e 将适合一个 int,这可能是不慎重的,但最终是合理的。您可能会发现 OpenSSL 更适合此目的,因为它倾向于对传递给它的数据做出更少的假设。