Class Ed25519

java.lang.Object
com.frostwire.jlibtorrent.Ed25519

public final class Ed25519 extends Object
Ed25519 elliptic curve cryptography for DHT and security operations.

Ed25519 provides a modern elliptic curve public-key signature system used in BitTorrent for DHT node identification, secure peer communication, and data integrity. Ed25519 is a variant of the Twisted Edwards curve offering better security and performance than RSA or traditional ECDSA, with signatures and keys only 32-64 bytes.

Understanding Ed25519:

  • Public Key (32 bytes): Shared openly, verifies signatures and receives encrypted messages
  • Secret Key (64 bytes): Private key kept secret, used for signing and decryption
  • Signature (64 bytes): Proof that a message was signed with a specific secret key
  • Seed (32 bytes): Random data that generates a keypair (deterministic)
  • Scalar (32 bytes): Parameter for key tweaking operations

Key Generation:

 // Create a new random seed
 byte[] seed = Ed25519.createSeed();  // 32 random bytes

 // Generate keypair from seed
 Pair<byte[], byte[]> keypair = Ed25519.createKeypair(seed);
 byte[] publicKey = keypair.first;    // 32 bytes - can be shared
 byte[] secretKey = keypair.second;   // 64 bytes - keep private

 System.out.println("Public key: " + Hex.encode(publicKey));
 System.out.println("Secret key: " + Hex.encode(secretKey));
 

Digital Signatures:

 // Sign a message
 byte[] message = "Important data".getBytes();
 byte[] signature = Ed25519.sign(message, publicKey, secretKey);

 // Verify signature (can be done with public key only)
 boolean isValid = Ed25519.verify(signature, message, publicKey);

 if (isValid) {
     System.out.println("Signature is valid - message is authentic");
 } else {
     System.out.println("Signature is invalid - message was tampered with or wrong key");
 }

 // Verification fails if message, signature, or key is changed
 byte[] tamperedMessage = "Modified data".getBytes();
 Ed25519.verify(signature, tamperedMessage, publicKey);  // false
 

Typical Workflow - DHT Node Identity:

 // Node setup (done once, saved for later)
 byte[] nodeSeed = Ed25519.createSeed();
 Pair<byte[], byte[]> nodeKeys = Ed25519.createKeypair(nodeSeed);
 byte[] nodePublicKey = nodeKeys.first;
 byte[] nodeSecretKey = nodeKeys.second;

 // Save these to disk for node persistence
 // On startup, load the same nodePublicKey and nodeSecretKey

 // Later: Sign DHT messages
 byte[] dhtMessage = constructDhtMessage(...);
 byte[] messageSignature = Ed25519.sign(dhtMessage, nodePublicKey, nodeSecretKey);

 // Peers verify our identity using nodePublicKey
 // They can verify without knowing nodeSecretKey
 

Key Tweaking Operations:

 // Scalar operations for advanced key derivation
 byte[] scalar = ...; // 32-byte scalar parameter

 // Add scalar to public key (for key derivation)
 byte[] derivedPublic = Ed25519.addScalarPublic(publicKey, scalar);

 // Add scalar to secret key (for key derivation)
 byte[] derivedSecret = Ed25519.addScalarSecret(secretKey, scalar);
 

Elliptic Curve Diffie-Hellman (ECDH):

 // Key exchange to establish shared secret
 byte[] peerPublicKey = receivePeerPublicKey();

 // Both parties can compute the same shared secret
 byte[] sharedSecret = Ed25519.keyExchange(peerPublicKey, localSecretKey);

 // Peer does: Ed25519.keyExchange(localPublicKey, peerSecretKey)
 // Result should be identical (symmetric)

 // Shared secret can be used as encryption key for further communication
 

Size Reference:

Ed25519 Cryptography Key Information
ComponentSize (bytes)BitsUsage
Seed32256Random data for key generation
Public Key32256Shared openly, for verification/encryption
Secret Key64512Private, for signing/decryption
Signature64512Proof of signing with secret key
Scalar32256Parameter for key operations
Shared Secret32256Symmetric key from ECDH

Security Properties:

  • 256-bit security level (pre-quantum)
  • Deterministic signatures (no randomness needed)
  • Immune to side-channel timing attacks
  • Small key size (32 bytes public key)
  • Fast signing and verification
  • Used by Signal, WireGuard, and modern protocols

BitTorrent Uses:

  • DHT v2 Node IDs: Ed25519 public keys identify nodes (replaces 20-byte SHA-1 IDs)
  • Mutable Items: Signed DHT items require Ed25519 signatures
  • Peer Authentication: Secure peer verification without certificates
  • Protocol Encryption: Key exchange for encrypted peer connections
See Also:
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    Size of public key: 32 bytes.
    static final int
    Size of scalar parameter for key tweaking: 32 bytes.
    static final int
    Size of secret (private) key: 64 bytes.
    static final int
    Size of the random seed for key generation: 32 bytes.
    static final int
    Size of shared secret from key exchange: 32 bytes.
    static final int
    Size of signature: 64 bytes.
  • Method Summary

    Modifier and Type
    Method
    Description
    static byte[]
    addScalarPublic(byte[] publicKey, byte[] scalar)
     
    static byte[]
    addScalarSecret(byte[] secretKey, byte[] scalar)
     
    static Pair<byte[],byte[]>
    createKeypair(byte[] seed)
     
    static byte[]
     
    byte[]
    keyExchange(byte[] publicKey, byte[] secretKey)
     
    static byte[]
    sign(byte[] message, byte[] publicKey, byte[] secretKey)
     
    static boolean
    verify(byte[] signature, byte[] message, byte[] publicKey)
     

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • SEED_SIZE

      public static final int SEED_SIZE
      Size of the random seed for key generation: 32 bytes.
      See Also:
    • PUBLIC_KEY_SIZE

      public static final int PUBLIC_KEY_SIZE
      Size of public key: 32 bytes. This is shared openly.
      See Also:
    • SECRET_KEY_SIZE

      public static final int SECRET_KEY_SIZE
      Size of secret (private) key: 64 bytes. Keep this private.
      See Also:
    • SIGNATURE_SIZE

      public static final int SIGNATURE_SIZE
      Size of signature: 64 bytes. Proof of signing with secret key.
      See Also:
    • SCALAR_SIZE

      public static final int SCALAR_SIZE
      Size of scalar parameter for key tweaking: 32 bytes.
      See Also:
    • SHARED_SECRET_SIZE

      public static final int SHARED_SECRET_SIZE
      Size of shared secret from key exchange: 32 bytes.
      See Also:
  • Method Details

    • createSeed

      public static byte[] createSeed()
    • createKeypair

      public static Pair<byte[],byte[]> createKeypair(byte[] seed)
    • sign

      public static byte[] sign(byte[] message, byte[] publicKey, byte[] secretKey)
    • verify

      public static boolean verify(byte[] signature, byte[] message, byte[] publicKey)
    • addScalarPublic

      public static byte[] addScalarPublic(byte[] publicKey, byte[] scalar)
    • addScalarSecret

      public static byte[] addScalarSecret(byte[] secretKey, byte[] scalar)
    • keyExchange

      public byte[] keyExchange(byte[] publicKey, byte[] secretKey)