mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2025-12-20 00:50:06 +08:00
80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
package encryption
|
|
|
|
import (
|
|
"crypto/ecdh"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"fmt"
|
|
|
|
"github.com/metacubex/blake3"
|
|
"github.com/metacubex/utls/mlkem"
|
|
)
|
|
|
|
const MLKEM768SeedLength = mlkem.SeedSize
|
|
const MLKEM768ClientLength = mlkem.EncapsulationKeySize768
|
|
const X25519PasswordSize = 32
|
|
const X25519PrivateKeySize = 32
|
|
|
|
func GenMLKEM768(seedStr string) (seedBase64, clientBase64, hash32Base64 string, err error) {
|
|
var seed [MLKEM768SeedLength]byte
|
|
if len(seedStr) > 0 {
|
|
s, _ := base64.RawURLEncoding.DecodeString(seedStr)
|
|
if len(s) != MLKEM768SeedLength {
|
|
err = fmt.Errorf("invalid length of ML-KEM-768 seed: %s", seedStr)
|
|
return
|
|
}
|
|
seed = [MLKEM768SeedLength]byte(s)
|
|
} else {
|
|
_, err = rand.Read(seed[:])
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
key, _ := mlkem.NewDecapsulationKey768(seed[:])
|
|
client := key.EncapsulationKey().Bytes()
|
|
hash32 := blake3.Sum256(client)
|
|
seedBase64 = base64.RawURLEncoding.EncodeToString(seed[:])
|
|
clientBase64 = base64.RawURLEncoding.EncodeToString(client)
|
|
hash32Base64 = base64.RawURLEncoding.EncodeToString(hash32[:])
|
|
return
|
|
}
|
|
|
|
func GenX25519(privateKeyStr string) (privateKeyBase64, passwordBase64, hash32Base64 string, err error) {
|
|
var privateKey [X25519PrivateKeySize]byte
|
|
if len(privateKeyStr) > 0 {
|
|
s, _ := base64.RawURLEncoding.DecodeString(privateKeyStr)
|
|
if len(s) != X25519PrivateKeySize {
|
|
err = fmt.Errorf("invalid length of X25519 private key: %s", privateKeyStr)
|
|
return
|
|
}
|
|
privateKey = [X25519PrivateKeySize]byte(s)
|
|
} else {
|
|
_, err = rand.Read(privateKey[:])
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
// Avoid generating equivalent X25519 private keys
|
|
// https://github.com/XTLS/Xray-core/pull/1747
|
|
//
|
|
// Modify random bytes using algorithm described at:
|
|
// https://cr.yp.to/ecdh.html.
|
|
privateKey[0] &= 248
|
|
privateKey[31] &= 127
|
|
privateKey[31] |= 64
|
|
|
|
key, err := ecdh.X25519().NewPrivateKey(privateKey[:])
|
|
if err != nil {
|
|
fmt.Println(err.Error())
|
|
return
|
|
}
|
|
password := key.PublicKey().Bytes()
|
|
hash32 := blake3.Sum256(password)
|
|
privateKeyBase64 = base64.RawURLEncoding.EncodeToString(privateKey[:])
|
|
passwordBase64 = base64.RawURLEncoding.EncodeToString(password)
|
|
hash32Base64 = base64.RawURLEncoding.EncodeToString(hash32[:])
|
|
return
|
|
}
|