github.com/xraypb/Xray-core@v1.8.1/main/commands/all/x25519.go (about)

     1  package all
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/base64"
     6  	"fmt"
     7  
     8  	"github.com/xraypb/Xray-core/main/commands/base"
     9  	"golang.org/x/crypto/curve25519"
    10  )
    11  
    12  var cmdX25519 = &base.Command{
    13  	UsageLine: `{{.Exec}} x25519 [-i "private key (base64.RawURLEncoding)"]`,
    14  	Short:     `Generate key pair for x25519 key exchange`,
    15  	Long: `
    16  Generate key pair for x25519 key exchange.
    17  
    18  Random: {{.Exec}} x25519
    19  
    20  From private key: {{.Exec}} x25519 -i "private key (base64.RawURLEncoding)"
    21  `,
    22  }
    23  
    24  func init() {
    25  	cmdX25519.Run = executeX25519 // break init loop
    26  }
    27  
    28  var input_base64 = cmdX25519.Flag.String("i", "", "")
    29  
    30  func executeX25519(cmd *base.Command, args []string) {
    31  	var output string
    32  	var err error
    33  	var privateKey []byte
    34  	var publicKey []byte
    35  	if len(*input_base64) > 0 {
    36  		privateKey, err = base64.RawURLEncoding.DecodeString(*input_base64)
    37  		if err != nil {
    38  			output = err.Error()
    39  			goto out
    40  		}
    41  		if len(privateKey) != curve25519.ScalarSize {
    42  			output = "Invalid length of private key."
    43  			goto out
    44  		}
    45  	}
    46  
    47  	if privateKey == nil {
    48  		privateKey = make([]byte, curve25519.ScalarSize)
    49  		if _, err = rand.Read(privateKey); err != nil {
    50  			output = err.Error()
    51  			goto out
    52  		}
    53  	}
    54  
    55  	// Modify random bytes using algorithm described at:
    56  	// https://cr.yp.to/ecdh.html.
    57  	privateKey[0] &= 248
    58  	privateKey[31] &= 127
    59  	privateKey[31] |= 64
    60  
    61  	if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil {
    62  		output = err.Error()
    63  		goto out
    64  	}
    65  
    66  	output = fmt.Sprintf("Private key: %v\nPublic key: %v",
    67  		base64.RawURLEncoding.EncodeToString(privateKey),
    68  		base64.RawURLEncoding.EncodeToString(publicKey))
    69  out:
    70  	fmt.Println(output)
    71  }