Table des matières
Contenu de la question
Solution
Maison développement back-end Golang Impossible de générer le certificat X.509 à l'aide de l'implémentation crypto.Signer personnalisée

Impossible de générer le certificat X.509 à l'aide de l'implémentation crypto.Signer personnalisée

Feb 10, 2024 pm 08:42 PM
加密货币

无法使用自定义 crypto.Signer 实现生成 X.509 证书

l'éditeur php Youzi est là pour vous présenter un problème de génération de certificats X.509. Parfois, lorsque vous utilisez une implémentation crypto.Signer personnalisée pour générer un certificat, vous pouvez rencontrer un problème inutilisable. Ce problème peut laisser les développeurs perplexes quant à la manière de le résoudre. Dans cet article, nous explorerons la cause de ce problème et proposerons des solutions pour aider les développeurs à générer avec succès leurs propres certificats X.509.

Contenu de la question

J'essaie de générer un certificat x.509 basé sur une paire de clés rsa stockée dans hsm. J'utilise cette implémentation pkcs #11 pour communiquer avec mon hsm.

Comme mes objets crypto sont stockés dans ce dernier, si une opération que je souhaite effectuer nécessite une clé privée (comme la signature), je dois implémenter l'interface crypto.signer afin de "accéder à la clé privée". C'est la mise en œuvre.

type rsasigner struct {
    privatekey p11.privatekey
    publickey  *rsa.publickey
}

func (s rsasigner) public() crypto.publickey {
    return s.publickey
}

func (s rsasigner) sign(_ io.reader, digest []byte, _ crypto.signeropts) ([]byte, error) {
    return s.privatekey.sign(pkcs11.mechanism{mechanism: pkcs11.ckm_sha512_rsa_pkcs}, digest)
}

func newrsasigner(privatekey p11.privatekey) (*rsasigner, error) {
    var (
        modulus, publicexponent []byte
        err                     error
    )

    // retrieve modulus n from the private key
    // reminder: n = p * q
    modulus, err = p11.object(privatekey).attribute(pkcs11.cka_modulus)
    if err != nil {
        return nil, err
    }

    // retrieve public exponent (e: "always" 65537) from the private key
    // reminder: φ(n) = (p - 1) * (q - 1), e such that 1 < e < φ(n) and e and φ(n) are co prime
    publicexponent, err = p11.object(privatekey).attribute(pkcs11.cka_public_exponent)
    if err != nil {
        return nil, err
    }

    // public key is (e, n)
    publickey := &rsa.publickey{
        n: new(big.int).setbytes(modulus),
        e: int(big.newint(0).setbytes(publicexponent).uint64()),
    }

    return &rsasigner{privatekey: privatekey, publickey: publickey}, nil
}
Copier après la connexion

Cette implémentation fonctionne. Par exemple, pour créer un csr, la fonction createcertificaterequest nécessite la clé privée pour signer le csr (là où se trouve l'instance priv any 参数),这是我提供 rsasigner.

La fonction

createcertificate est quelque peu similaire, le paramètre pub是要生成的证书的公钥,priv est la clé privée du signataire.

Dans le code ci-dessous, j'essaie de générer un certificat x.509 auto-signé, donc les templateparentparamètres sont les mêmes selon l'API.

func (t *token) x509(id, objecttype, output string) ([]time.duration, error) {
    startfunction := time.now()

    var (
        keytype            int
        privatekeytemplate []*pkcs11.attribute
        privatekeyobject   p11.object
        err                error
        timings            []time.duration
        signer             *rsasigner
        cert               []byte
        file               *os.file
        writtenbytes       int
    )

    objecttype = strings.tolower(objecttype)

    if objecttype != "rsa" && objecttype != "ec" {
        logger.fatalf("%s: unrecognized type, it can only be equal to rsa or ec", objecttype)
    }

    switch objecttype {
    case "rsa":
        keytype = pkcs11.ckk_rsa
    case "ec":
        keytype = pkcs11.ckk_ec
    }

    // creation of the template to find the private key based on the given id (pkcs #11 attribute cka_id)
    privatekeytemplate = []*pkcs11.attribute{
        pkcs11.newattribute(pkcs11.cka_key_type, keytype),
        pkcs11.newattribute(pkcs11.cka_class, pkcs11.cko_private_key),
        pkcs11.newattribute(pkcs11.cka_id, id),
    }

    startfindobject := time.now()
    privatekeyobject, err = t.session.findobject(privatekeytemplate)
    timings = append(timings, time.since(startfindobject))
    if err != nil {
        return nil, err
    }

    // creation of the x.509 certificate template
    certtemplate := &x509.certificate{
        serialnumber: big.newint(2023),
        subject: pkix.name{
            commonname: "test",
        },
        signaturealgorithm: x509.sha512withrsa,
        notbefore:          time.now(),
        notafter:           time.now().adddate(1, 0, 0),
    }

    // instantiate the rsasigner with the found private key object
    signer, err = newrsasigner(p11.privatekey(privatekeyobject))
    if err != nil {
        return nil, err
    }

    startcreatecert := time.now()
    cert, err = x509.createcertificate(rand.reader, certtemplate, certtemplate, signer.publickey, signer)
    timings = append(timings, time.since(startcreatecert))
    if err != nil {
        return nil, err
    }

    file, err = os.create(output)
    if err != nil {
        return nil, err
    }

    writtenbytes, err = file.write(cert)
    if err != nil {
        return nil, err
    }

    logger.printf("wrote %d bytes in %s", writtenbytes, output)

    return append(timings, time.since(startfunction)), nil
}
Copier après la connexion

Quel que soit le type de clé (rsa ou ec), cette fonction renvoie l'erreur suivante.

FATA[2022-12-22 10:48:50] x509: signature over certificate returned by signer is invalid: crypto/rsa: verification error
Copier après la connexion

Cette erreur sera renvoyée si l'implémentation crypto.signer n'est pas terminée correctement.

J'ai implémenté crypto.signer pour essayer de faire la même chose en utilisant des paires de clés sur des courbes elliptiques, mais l'erreur est la même.

J'ai également essayé différents algorithmes de hachage dans la fonction sign mais cela n'a rien changé.

L'erreur semble provenir de l'implémentation de crypto.signer bien qu'elle puisse être utilisée pour générer du csr.

Solution

Bien que j'ai trouvé la solution à ce problème il y a des mois, je n'ai jamais pris le temps de partager la réponse, cependant, c'est le moment.

Lorsque nous signons directement via pkcs #11, nous devons gérer le préfixe de hachage en préfixant manuellement le hachage en utilisant la valeur digestinfo référencée ici : https://www.rfc-editor.org/rfc /rfc3447#page-43 .

Plus précisément, pour la signature rsassa-pkcs1-v1_5, l'entrée de la fonction de signature réelle est une structure codée asn.1 der. pkcs #11 a des mécanismes spécifiques au hachage (par exemple ckm_sha256_rsa_pkcs) qui savent comment générer la structure, mais ils supposent tous que les données ne sont pas hachées, ce qui n'est pas le cas des crypto-monnaies. signer, nous devons donc utiliser le mécanisme générique cka_rsa_pkcs, qui effectue uniquement des opérations de signature brutes. Cela signifie que nous devons générer nous-mêmes la structure asn.1, ce que nous pouvons faire en fournissant simplement le préfixe correct pour tous les hachages que nous pourrions vouloir utiliser.

À l'aide du paramètre opts de type crypto.signeropts nous pouvons récupérer l'identifiant d'une fonction de hachage de type crypto.hash lorsque la fonction sign() est appelée, avec le préfixe correct appliqué.

type signer struct {
    prikey p11.privatekey
    pubkey *rsa.publickey
}

var hashprefixes = map[crypto.hash][]byte{
    crypto.sha256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
    crypto.sha384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
    crypto.sha512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
}

func (s signer) public() crypto.publickey {
    return s.pubkey
}

func (s signer) sign(_ io.reader, digest []byte, opts crypto.signeropts) ([]byte, error) {
    return s.prikey.sign(*pkcs11.newmechanism(pkcs11.ckm_rsa_pkcs, nil), append(hashprefixes[opts.hashfunc()], digest...))
}

func newsigner(key p11.privatekey) (*signer, error) {
    // retrieve modulus n from the private key
    // reminder: n = p * q
    modulus, err := p11.object(key).attribute(pkcs11.cka_modulus)
    if err != nil {
        return nil, err
    }

    var pubexp []byte
    // retrieve public exponent (e: "always" 65537) from the private key
    // reminder: φ(n) = (p - 1) * (q - 1), e such that 1 < e < φ(n) and e and φ(n) are co prime
    pubexp, err = p11.object(key).attribute(pkcs11.cka_public_exponent)
    if err != nil {
        return nil, err
    }

    // public key is (e, n)
    pubkey := &rsa.publickey{
        n: new(big.int).setbytes(modulus),
        e: int(new(big.int).setbytes(pubexp).uint64()),
    }

    return &signer{prikey: key, pubkey: pubkey}, nil
}
Copier après la connexion

Cela fonctionne à merveille. Il y a cependant de meilleures choses à faire.

Le mécanisme

ckm_rsa_pkcs fournit des signatures de type rsassa-pkcs1-v1_5. Je laisse aux lecteurs intéressés le soin d'étudier par eux-mêmes cet ancien schéma de signature, qui ne devrait plus être utilisé dans les nouveaux produits/logiciels.

En effet, il est recommandé d'utiliser le mécanisme ckm_rsa_pkcs_pss, qui fournit des signatures de type rsassa-pss.

Partant de ce principe, c'est l'implémentation que j'utilise maintenant.

type Signer struct {
    priKey p11.PrivateKey
    pubKey *rsa.PublicKey
}

var sigAlg = map[crypto.Hash]uint{
    crypto.SHA256: pkcs11.CKM_SHA256_RSA_PKCS_PSS,
    crypto.SHA384: pkcs11.CKM_SHA384_RSA_PKCS_PSS,
    crypto.SHA512: pkcs11.CKM_SHA512_RSA_PKCS_PSS,
}

var mgf = map[crypto.Hash]uint{
    crypto.SHA256: pkcs11.CKG_MGF1_SHA256,
    crypto.SHA384: pkcs11.CKG_MGF1_SHA384,
    crypto.SHA512: pkcs11.CKG_MGF1_SHA512,
}

func (s Signer) Public() crypto.PublicKey {
    return s.pubKey
}

func (s Signer) Sign(_ io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
    return s.priKey.Sign(*pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_PSS, pkcs11.NewPSSParams(sigAlg[opts.HashFunc()], mgf[opts.HashFunc()], uint(opts.HashFunc().Size()))), digest)
}

func NewSigner(key p11.PrivateKey) (*Signer, error) {
    // Retrieve modulus n from the private key
    // Reminder: n = p * q
    modulus, err := p11.Object(key).Attribute(pkcs11.CKA_MODULUS)
    if err != nil {
        return nil, err
    }

    var pubExp []byte
    // Retrieve public exponent (e: "always" 65537) from the private key
    // Reminder: φ(n) = (p - 1) * (q - 1), e such that 1 < e < φ(n) and e and φ(n) are co prime
    pubExp, err = p11.Object(key).Attribute(pkcs11.CKA_PUBLIC_EXPONENT)
    if err != nil {
        return nil, err
    }

    // Public key is (e, n)
    pubKey := &rsa.PublicKey{
        N: new(big.Int).SetBytes(modulus),
        E: int(new(big.Int).SetBytes(pubExp).Uint64()),
    }

    return &Signer{priKey: key, pubKey: pubKey}, nil
}
Copier après la connexion

Le préfixe n'est donc plus nécessaire, mais la correspondance entre l'identifiant de l'algorithme de hachage et l'algorithme de signature à utiliser et le mgf à utiliser est requise.

Enfin, en go, l'algorithme de signature utilisé n'est plus x509.sha256withrsa, x509.sha384withrsa ou x509.sha512withrsa, mais sha256withrsapss, 4withrsapss et sha512withrsapss.

Bonne signature.

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

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

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)

OKX OUYI Exchange Version Web Entrez le lien Cliquez pour entrer OKX OUYI Exchange Version Web Entrez le lien Cliquez pour entrer Mar 31, 2025 pm 06:21 PM

1. Entrez la version Web d'OKX EUYI Exchange ☜☜☜☜☜☜ Cliquez pour enregistrer 2. Cliquez sur le lien de l'application OKX EUYI Exchange ☜☜☜☜ Cliquez pour enregistrer 3. Après être entré sur le site officiel, l'interface Efface fournit un portail de connexion et d'enregistrement. Les utilisateurs peuvent choisir de se connecter à un compte existant ou d'enregistrer un nouveau compte en fonction de leur propre situation. Qu'il s'agisse de visualiser les conditions du marché en temps réel, de mener des transactions ou de gérer des actifs, la version Web OKX offre une expérience de fonctionnement simple et fluide, adaptée aux débutants et aux anciens combattants. Visitez le site officiel OKX maintenant pour une expérience facile

Tutoriel d'enregistrement GATE.IO Tutoriel d'enregistrement GATE.IO Mar 31, 2025 pm 11:09 PM

Cet article fournit un didacticiel d'inscription GATE.IO détaillé, couvrant chaque étape de l'accès au site officiel à la réalisation de l'enregistrement, notamment le remplissage des informations d'enregistrement, la vérification, la lecture des accords d'utilisateurs, etc. L'article est également en vigueur les mesures de sécurité après une inscription réussie, telles que la configuration de la vérification secondaire et la réalisation de l'authentification réelle, et donne des conseils à partir des débutants pour aider les utilisateurs secondaires à démarrer en toute sécurité leur parcours numérique.

À quoi sert Ouli? Qu'est-ce que Ouyi À quoi sert Ouli? Qu'est-ce que Ouyi Apr 01, 2025 pm 03:18 PM

OKX est une plate-forme mondiale de trading d'actifs numériques. Ses principales fonctions incluent: 1. Achat et vente d'actifs numériques (trading au comptant), 2. Trading entre les actifs numériques, 3. Fournir des conditions et des données du marché, 4. Fournir des produits de trading diversifiés (tels que les dérivés), 5. Fournir des services à valeur ajoutée des actifs, 6. Management des actifs pratique.

OK Portail officiel Version Web OK Exchange OK Portail officiel Version Web OK Exchange Mar 31, 2025 pm 06:24 PM

Cet article détaille comment utiliser la version Web officielle d'OK Exchange pour se connecter. Les utilisateurs doivent uniquement rechercher "OK ​​Exchange Version Web officielle" dans leur navigateur, cliquez sur le bouton de connexion dans le coin supérieur droit après être entré sur le site Web officiel, et saisir le nom d'utilisateur et le mot de passe pour se connecter. Les utilisateurs enregistrés peuvent facilement gérer les actifs, effectuer des transactions, des dépôts et retirer des fonds, etc. L'interface officielle du site Web est simple et facile à utiliser, et fournit un soutien client complet pour assurer que les utilisateurs de la douceur ne sont que des échanges sur l'organisation. Qu'attendez-vous? Visitez le site officiel d'OK Exchange maintenant pour commencer votre parcours d'actifs numériques!

Binance Binance Version de l'ordinateur Entrée Binance Binance Version de l'ordinateur PC Entrée de connexion officielle du site Web Binance Binance Version de l'ordinateur Entrée Binance Binance Version de l'ordinateur PC Entrée de connexion officielle du site Web Mar 31, 2025 pm 04:36 PM

Cet article fournit un guide complet de connexion et d'enregistrement sur la version Binance PC. Tout d'abord, nous avons expliqué en détail les étapes de connexion en binance PC Version: Recherchez le "site officiel de Binance" dans le navigateur, cliquez sur le bouton de connexion, entrez l'e-mail et le mot de passe (Activer 2FA pour entrer le code de vérification) pour vous connecter. Deuxièmement, l'article explique le processus d'e-mail: cliquez sur le bouton "Inscrivez-vous", remplissez l'adresse e-mail, définissez un mot de passe fort et Verifiez l'adresse de l'e-mail pour terminer l'affichage de l'inscription. Enfin, l'article met également l'accent sur la sécurité du compte, rappelant aux utilisateurs de prêter attention au nom de domaine officiel, à l'environnement réseau et à la mise à jour régulière des mots de passe pour assurer la sécurité des comptes et une meilleure utilisation des diverses fonctions fournies par la version Binance PC, telles que la visualisation des conditions du marché, la réalisation de transactions et la gestion des actifs.

Quels sont les sites Web recommandés pour le logiciel d'application de devise virtuelle? Quels sont les sites Web recommandés pour le logiciel d'application de devise virtuelle? Mar 31, 2025 pm 09:06 PM

Cet article recommande dix sites de recommandation d'applications liés à la monnaie virtuelle bien connus, notamment Binance Academy, Okx Learn, Coingecko, Cryptoslate, Coindesk, Investopedia, CoinmarketCap, Huobi University, Coinbase Learn et Cryptocompare. Ces sites Web fournissent non seulement des informations telles que les données du marché des devises virtuelles, l'analyse des tendances des prix, etc., mais fournissent également des ressources d'apprentissage riches, y compris les connaissances de base de la blockchain, les stratégies de trading et les didacticiels et les avis de diverses applications de plate-forme de trading, aidant les utilisateurs à mieux comprendre et à en faire usage

COMMOCE DE SITEET OFFICIELLE DU NAISSE DE COMMANDE 2025 COMMOCE DE SITEET OFFICIELLE DU NAISSE DE COMMANDE 2025 Mar 31, 2025 pm 03:57 PM

Il se classe parmi les meilleurs du monde, prend en charge toutes les catégories de transactions telles que Spot, Contracts et WEB3 Wallet. Il a des frais de haute sécurité et de manipulation faible. Une plate-forme de trading complète avec une longue histoire, connue pour sa conformité et sa haute liquidité, prend en charge les services multilingues. Le leader de l'industrie couvre le trading de devises, l'effet de levier, les options, etc., avec une forte liquidité et soutient les frais de déduction BNB.

Sur quelle plateforme est la transaction Web3? Sur quelle plateforme est la transaction Web3? Mar 31, 2025 pm 07:54 PM

Cet article répertorie les dix principales plateformes de trading Web3 bien connues, notamment Binance, Okx, Gate.io, Kraken, Bybit, Coinbase, Kucoin, Bitget, Gemini et Bitstamp. L'article compare les caractéristiques de chaque plate-forme en détail, tels que le nombre de devises, les types de trading (spot, futures, options, NFT, etc.), les frais de traitement, la sécurité, la conformité, les groupes d'utilisateurs, etc., visant à aider les investisseurs à choisir la plate-forme de négociation la plus appropriée. Qu'il s'agisse de commerçants à haute fréquence, de passionnés de trading de contrats ou d'investisseurs qui se concentrent sur la conformité et la sécurité, ils peuvent en trouver des informations de référence.

See all articles