1
votes

Comment générer une clé publique pour une clé privée dans X25519?

Je travaille actuellement avec un chiffrement basé sur les clés X25519.

Ma question est, en gros, comment dériver PublicKey à partir de X25519 PrivateKey ?

J'ai trouvé le code dans le XDHKeyPairGenerator:

BigInteger publicKey = ops.computePublic(privateKey.clone());

Mais ce paquet est spécifique à la plate-forme, donc non accessible. Et je ne trouve pas de méthode pour le faire via des interfaces accessibles au public.


0 commentaires

3 Réponses :


2
votes

Vous devez multiplier de manière scalaire la clé privée (qui n'est qu'un grand nombre) par le point du générateur de courbes 25519 .

Ici est un code en python pour illustrer:

from tinyec import registry
import secrets

curve = registry.get_curve('curve25519')

def compress_point(point):
    return hex(point.x) + hex(point.y % 2)[2:]


privKey = secrets.randbelow(curve.field.n)
pubKey = privKey * curve.g //the key step for you...


print("private key:", hex(privKey))
print("public key:", compress_point(pubKey))

Si vous me faites connaître la bibliothèque Java, je vais essayer de vous aider.


4 commentaires

Ressemble à Java 11+, pas de bibliothèques supplémentaires.


J'obtiens une hausse ValueError ("Nom de la courbe elliptique inconnue")


@Markkkkk oui, c'est juste parce qu'il ne reconnaît pas la courbe que vous spécifiez


@Woodstock, je l'ai remarqué. Je me demandais quel était le nom correct de la courbe elliptique pour 25519 dans le registre tinyec? J'ai cherché partout une solution python à ce sujet. Toujours pas de chance.



1
votes

Jusqu'à présent, je n'ai découvert qu'une seule façon de le faire via les interfaces fournies par JDK (sans utiliser de bibliothèques supplémentaires telles que Bouncy Castle ou Google Tink):

    public PublicKey generatePublicKeyFromPrivate(PrivateKey privateKey) throws GeneralSecurityException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(X25519);
        keyPairGenerator.initialize(new NamedParameterSpec(X25519), new StaticSecureRandom(getScalar(privateKey)));
        return keyPairGenerator.generateKeyPair().getPublic();
    }
public class StaticSecureRandom extends SecureRandom {

    private final byte[] privateKey;

    public StaticSecureRandom(byte[] privateKey) {
        this.privateKey = privateKey.clone();
    }

    @Override
    public void nextBytes(byte[] bytes) {
        System.arraycopy(privateKey, 0, bytes, 0, privateKey.length);
    }

}

Ce n'est pas une solution très élégante, mais elle fonctionne sans aucune bibliothèque tierce et je n'ai pas trouvé d'autre moyen.


0 commentaires

0
votes

BouncyCastle a Ed25519KeyPairGenerator, X25519KeyPairGenerator, PrivateKeyInfoFactory et SubjectPublicKeyInfoFactory qui peuvent vous aider à créer les clés. Voici un exemple en C #. Remplacez ECKeyPairGenerator par X25519KeyPairGenerator. Cet exemple utilise des clés standard et une courbe NIST car je n'ai pas pu faire fonctionner Curve25519 avec les clés générées par X25519 car l'OID n'est pas pris en charge dans l'implémentation actuelle.

public static async Task Bouncy()
    {
        var originalSecret = "X25519 example";
        var message = Encoding.UTF8.GetBytes(originalSecret);

        // Generate signing keys
        var gen = new Ed25519KeyPairGenerator();
        gen.Init(new Ed25519KeyGenerationParameters(new SecureRandom()));
        var kp = gen.GenerateKeyPair();

        // Sign data with private key
        var signer = new Ed25519Signer();
        signer.Init(true, kp.Private);
        signer.BlockUpdate(message, 0, message.Length);
        var sig = signer.GenerateSignature();

        // Verify signature with public key
        var verifier = new Ed25519Signer();
        verifier.Init(false, kp.Public);
        verifier.BlockUpdate(message, 0, message.Length);
        var sigresult = verifier.VerifySignature(sig);

        // Generate encryption keys
        var genX = new ECKeyPairGenerator();
        genX.Init(new KeyGenerationParameters(new SecureRandom(), 521));

        var p1 = genX.GenerateKeyPair();
        var p1_private = ECPrivateKeyStructure.GetInstance(PrivateKeyInfoFactory.CreatePrivateKeyInfo(p1.Private));
        var p1_x25519_priv = new X25519PrivateKeyParameters(p1_private.GetDerEncoded(), 0);

        var p2 = genX.GenerateKeyPair();
        var p2_public = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(p2.Public);
        var p2_x25519_pub = new X25519PublicKeyParameters(p2_public.GetDerEncoded(), 0);

        // Generate secret from keys
        var secret = new byte[32];
        p1_x25519_priv.GenerateSecret(p2_x25519_pub, secret, 0);

        // Setup ECIES (Elliptical Curve Integrated Encryption Scheme)
        var gcm = new GcmBlockCipher(new AesEngine());
        var ies = new IesEngine(new ECDHBasicAgreement(), new Kdf2BytesGenerator(new Sha512Digest()),
            new HMac(new Sha512Digest()), new PaddedBufferedBlockCipher(gcm.GetUnderlyingCipher()));

        // 256bit MAC, 256 key
        var p = new IesWithCipherParameters(secret, new byte[1], 256, 256);

        // Encrypt secret
        ies.Init(true, p1.Private, p2.Public, p);
        var encrypted = ies.ProcessBlock(message, 0, message.Length);

        // Decrypt secret
        ies.Init(false, p2.Private, p1.Public, p);
        var decrypted = ies.ProcessBlock(encrypted, 0, encrypted.Length);
        var decrypted_string = Encoding.UTF8.GetString(decrypted);
    }


0 commentaires