简体   繁体   中英

Curve25519 public key is 309 bytes and private key is 587. Shouldn't it be 32 bytes?

I am trying to implement curve25519 in my java program using bouncycastle, and this is the code I've come up with:

package crypto;

import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;

public class Curve {

    public KeyPair generateKeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        X9ECParameters ecP = CustomNamedCurves.getByName("curve25519");
        ECParameterSpec ecSpec = new ECParameterSpec(ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed());
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
        keyGen.initialize(ecSpec);
        return keyGen.generateKeyPair();
    }

}

And my main method:

package crypto;

import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class Test_Curve {

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        Curve curve = new Curve();
        KeyPair keys = curve.generateKeyPair();
        System.out.println(keys.getPrivate().getEncoded().length);
        System.out.println(keys.getPublic().getEncoded().length);
        System.out.println(new String(Base64.getEncoder().encode(keys.getPrivate().getEncoded()), StandardCharsets.US_ASCII));
        System.out.println(new String(Base64.getEncoder().encode(keys.getPublic().getEncoded()), StandardCharsets.US_ASCII));
    }

}

This is the output I get from my program:

587
309
MIICRwIBADCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCASCAVMwggFPAgEBBCALaQ79+nbqlaXL3aLfYSIMRPzMgKxdayqZA7WQ20XhhaCB4TCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCKFEA0IABCsAt6tKs2ZiLn85ggNCjdx++vGIwNOI0X0OsXscSMgOBzCpMDGDOdt1ejV5LiPqorjd6fIIZG4PWCXjvjxCO+M=
MIIBMTCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCANCAAQrALerSrNmYi5/OYIDQo3cfvrxiMDTiNF9DrF7HEjIDgcwqTAxgznbdXo1eS4j6qK43enyCGRuD1gl4748Qjvj

However, this doesn't seem right to me. I read that curve25519 public keys are supposed to be 32 bytes, and this clearly isn't. I've done my due diligence and pulled several examples from google and tried them out, but still ran into the same issue. Any help is greatly appreciated.

Curve25519 is not an X9/Weierstrass curve. What you are doing won't be compatible with other implementations, which all use Bernstein's specifications for either X-only Montgomery-form Diffie-Hellman called X25519 or Edwards-form signature (normally without prehash) called Ed25519. The key encoding used by Java for all asymmetric keys (both public and private) is never just the key itself but a generic encoding that includes metadata, either X.509 SPKI or PKCS8 and by forcing this curve first to Weierstrass form (for X9) and then to unnamed form by using the explicit and long-obsolete X9 form of ECParameterSpec you hugely bloat that metadata.

Instead use the algorithm "X25519" or "ED25519" in both KeyPairGenerator and subsequent KeyAgreement or Signature respectively. The standard encodings will still be longer than the raw key, but by much less. To get the raw key, in Oracle/Open use as appropriate the interfaces {XEC,EdEC}{Public,Private}Key which are implemented by the algorithm-dependent implementation (provider) classes. (edit) Recent Bouncy (1.65 up) run on sufficiently recent Java also does this; otherwise AFAICS you must get the generic (ASN.1) encoding and parse it -- Bouncy does expose that (ASN.1) functionality separately (through its 'lightweight' API not JCA) (and has since roughly the dawn of time).

I am trying to implement curve25519 in my java program using bouncycastle

My condolences.

Your problem is that you are outputting Base64-encoded ASN.1 instead of just the public or private key. This decoder applied to your second output shows the actual private key. Note that the point is not compressed, so both X and Y coordinates are present (the two 32-byte octet strings).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM