Maison > développement back-end > Golang > le corps du texte

Générez de manière déterministe des clés privées RSA avec io.Reader personnalisé à l'aide de Go

WBOY
Libérer: 2024-02-09 14:12:10
avant
371 Les gens l'ont consulté

使用 Go 通过自定义 io.Reader 确定性生成 RSA 私钥

L'éditeur php Baicao présentera comment utiliser le langage Go pour générer de manière déterministe des clés privées RSA via une interface io.Reader personnalisée. RSA est un algorithme de chiffrement asymétrique couramment utilisé pour le chiffrement des données et les signatures numériques. Lors de la génération d'une clé privée RSA, nous devons généralement obtenir des nombres aléatoires à partir d'une source aléatoire, mais nous devons parfois générer une clé privée déterministe selon des règles spécifiques. Cet article expliquera en détail comment implémenter une interface io.Reader personnalisée et utiliser cette interface pour générer une clé privée RSA déterministe. En lisant cet article, vous apprendrez cette technique utile pour donner plus de flexibilité et de contrôle à vos applications cryptographiques.

Contenu de la question

Pour des raisons qu'il vaut probablement mieux laisser sans réponse, je dois générer un nombre illimité de clés publiques/privées rsa. Notez que cela n’est utilisé pour rien de hautement sécurisé, alors ne me dites pas de ne pas le faire, et oui, je sais que ce n’est pas idéal. Ce que je veux dire par « infini », c'est que j'en ai besoin d'un nombre inconnu (des milliards à des milliards) et qu'il est impossible de les créer avant de les utiliser.

Étant donné que cela consomme un espace infini et prend un temps infini à générer, je dois le faire au moment de l'exécution.

Cependant, j'ai également besoin d'avoir la même paire de clés pour une entrée donnée. Cela signifie que je dois recréer de manière déterministe la clé rsa en fonction de l'entrée.

J'utilise go, généralement vous créez la clé en utilisant la commande suivante,

k, err := rsa.generatekey(rand.reader, 2048)
Copier après la connexion

Bien sûr, le problème est que rand.reader 是由 crypto/rand est fourni, il ne peut donc pas être semé.

Je pensais qu'il serait possible de fournir ma propre implémentation de lecteur pour atteindre mon objectif. J'ai regardé le code source de generatekey et j'ai remarqué qu'il recherchait des nombres premiers, j'ai donc implémenté mon propre lecteur afin de pouvoir contrôler les nombres premiers "aléatoires" renvoyés, me permettant de générer la même clé si nécessaire,

type reader struct {
    data   []byte
    sum    int
    primes []int
}

func newreader(toread string) *reader {
    primes := sieveoferatosthenes(10_000_000)
    return &reader{[]byte(toread), 0, primes}
}

func (r *reader) read(p []byte) (n int, err error) {
    r.sum = r.sum + 1

    if r.sum >= 100_000 {
        return r.primes[rand.intn(len(r.primes))], io.eof
    }

    return r.primes[rand.intn(len(r.primes))], nil
}

func sieveoferatosthenes(n int) (primes []int) {
    b := make([]bool, n)
    for i := 2; i < n; i++ {
        if b[i] == true {
            continue
        }
        primes = append(primes, i)
        for k := i * i; k < n; k += i {
            b[k] = true
        }
    }
    return
}
Copier après la connexion

Ensuite, je peux appeler générer une clé comme celle-ci

k, err := rsa.GenerateKey(NewReader(""), 2048)
Copier après la connexion

Il se compile mais plante au moment de l'exécution en raison de pointeurs nuls. Je suis plutôt content de go, mais la mise en œuvre de rsa dépasse ma compréhension. Je cherche de meilleures façons d’y parvenir ou ce que je dois faire pour que cela fonctionne pour mes lecteurs.

Notez que ma seule exigence ici est de pouvoir générer la même clé pour une entrée donnée, en utilisant rsa.generatekey ou une substitution compatible. L'entrée peut être littéralement n'importe quoi tant que j'obtiens la même clé que la sortie.

Voici un lien Go Playground montrant où je me trouve actuellement sur https://go.dev/play/p/jd1naopr5ad

Workaround

read 方法未执行预期操作。它不会用随机字节填充输入 p 字节切片。如果您查看 crypto/rand.read Une implémentation Unix d'une méthode qui transmet une tranche d'octets d'entrée à un autre lecteur. Donc, fondamentalement, vous devez remplir la tranche d'octets avec des nombres aléatoires. Par exemple :

func (r *reader) read(p []byte) (n int, err error) {
        i := 0
        b := p

        for i < len(b) {
                if len(b) < 4 {
                        b[0] = 7
                        b = b[1:]
                } else {
                        binary.littleendian.putuint32(b, uint32(rand.intn(len(r.primes))))
                        b = b[4:]
                }
        }

        return len(p), nil
}
Copier après la connexion

C'est le lien vers le terrain de jeu.

Mise à jour

Comme Erwin l'a mentionné dans sa réponse, il existe une fonction appelée maybereadrand qui a 50 % de chances de lire 1 octet du lecteur Rand, ce qui rend la fonction non déterministe. Mais vous pouvez le résoudre en ajoutant une instruction if dans la méthode read : si la longueur de la tranche d'entrée est de 1, ignorez tout et revenez. Sinon, fournissez des nombres premiers à la tranche d'entrée :

func (r *Reader) Read(p []byte) (n int, err error) {
    i := 0
    b := p

    if len(p) == 1 {
        println("maybeReadRand")
        return 1, nil
    }

    for i < len(b) {
        if len(b) < 4 {
            b[0] = 7
            b = b[1:]
        } else {
            binary.LittleEndian.PutUint32(b, uint32(r.primes[r.i]))
            r.i++
            b = b[4:]
        }
    }

    return len(p), nil
}
Copier après la connexion

Dans cet extrait, j'ai créé 2 clés et elles sont toutes deux égales. p>

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!