Table des matières
Contenu de la question
Workaround
Maison développement back-end Golang Générez de manière déterministe des clés privées RSA avec io.Reader personnalisé à l'aide de Go

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

Feb 09, 2024 pm 02:12 PM
go语言

使用 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!

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

Article chaud

Repo: Comment relancer ses coéquipiers
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD
R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Article chaud

Repo: Comment relancer ses coéquipiers
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD
R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Tags d'article chaud

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment utiliser la réflexion pour accéder aux champs et méthodes privés dans Golang Comment utiliser la réflexion pour accéder aux champs et méthodes privés dans Golang May 03, 2024 pm 12:15 PM

Comment utiliser la réflexion pour accéder aux champs et méthodes privés dans Golang

Conseils pour créer dynamiquement de nouvelles fonctions dans les fonctions Golang Conseils pour créer dynamiquement de nouvelles fonctions dans les fonctions Golang Apr 25, 2024 pm 02:39 PM

Conseils pour créer dynamiquement de nouvelles fonctions dans les fonctions Golang

La différence entre les tests de performances et les tests unitaires en langage Go La différence entre les tests de performances et les tests unitaires en langage Go May 08, 2024 pm 03:09 PM

La différence entre les tests de performances et les tests unitaires en langage Go

À quels pièges devons-nous prêter attention lors de la conception de systèmes distribués avec la technologie Golang ? À quels pièges devons-nous prêter attention lors de la conception de systèmes distribués avec la technologie Golang ? May 07, 2024 pm 12:39 PM

À quels pièges devons-nous prêter attention lors de la conception de systèmes distribués avec la technologie Golang ?

Bibliothèques technologiques Golang et outils utilisés dans l'apprentissage automatique Bibliothèques technologiques Golang et outils utilisés dans l'apprentissage automatique May 08, 2024 pm 09:42 PM

Bibliothèques technologiques Golang et outils utilisés dans l'apprentissage automatique

L'évolution de la convention de dénomination des fonctions Golang L'évolution de la convention de dénomination des fonctions Golang May 01, 2024 pm 03:24 PM

L'évolution de la convention de dénomination des fonctions Golang

Le rôle de la technologie Golang dans le développement de l'IoT mobile Le rôle de la technologie Golang dans le développement de l'IoT mobile May 09, 2024 pm 03:51 PM

Le rôle de la technologie Golang dans le développement de l'IoT mobile

Les paramètres de variables Golang peuvent-ils être utilisés pour les valeurs de retour de fonction ? Les paramètres de variables Golang peuvent-ils être utilisés pour les valeurs de retour de fonction ? Apr 29, 2024 am 11:33 AM

Les paramètres de variables Golang peuvent-ils être utilisés pour les valeurs de retour de fonction ?

See all articles