ech_keygen.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package tls
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "encoding/pem"
  6. E "github.com/sagernet/sing/common/exceptions"
  7. "github.com/cloudflare/circl/hpke"
  8. "github.com/cloudflare/circl/kem"
  9. )
  10. func ECHKeygenDefault(serverName string) (configPem string, keyPem string, err error) {
  11. cipherSuites := []echCipherSuite{
  12. {
  13. kdf: hpke.KDF_HKDF_SHA256,
  14. aead: hpke.AEAD_AES128GCM,
  15. }, {
  16. kdf: hpke.KDF_HKDF_SHA256,
  17. aead: hpke.AEAD_ChaCha20Poly1305,
  18. },
  19. }
  20. keyConfig := []myECHKeyConfig{
  21. {id: 0, kem: hpke.KEM_X25519_HKDF_SHA256},
  22. }
  23. keyPairs, err := echKeygen(0xfe0d, serverName, keyConfig, cipherSuites)
  24. if err != nil {
  25. return
  26. }
  27. var configBuffer bytes.Buffer
  28. var totalLen uint16
  29. for _, keyPair := range keyPairs {
  30. totalLen += uint16(len(keyPair.rawConf))
  31. }
  32. binary.Write(&configBuffer, binary.BigEndian, totalLen)
  33. for _, keyPair := range keyPairs {
  34. configBuffer.Write(keyPair.rawConf)
  35. }
  36. var keyBuffer bytes.Buffer
  37. for _, keyPair := range keyPairs {
  38. keyBuffer.Write(keyPair.rawKey)
  39. }
  40. configPem = string(pem.EncodeToMemory(&pem.Block{Type: "ECH CONFIGS", Bytes: configBuffer.Bytes()}))
  41. keyPem = string(pem.EncodeToMemory(&pem.Block{Type: "ECH KEYS", Bytes: keyBuffer.Bytes()}))
  42. return
  43. }
  44. type echKeyConfigPair struct {
  45. id uint8
  46. rawKey []byte
  47. conf myECHKeyConfig
  48. rawConf []byte
  49. }
  50. type echCipherSuite struct {
  51. kdf hpke.KDF
  52. aead hpke.AEAD
  53. }
  54. type myECHKeyConfig struct {
  55. id uint8
  56. kem hpke.KEM
  57. seed []byte
  58. }
  59. func echKeygen(version uint16, serverName string, conf []myECHKeyConfig, suite []echCipherSuite) ([]echKeyConfigPair, error) {
  60. be := binary.BigEndian
  61. // prepare for future update
  62. if version != 0xfe0d {
  63. return nil, E.New("unsupported ECH version", version)
  64. }
  65. suiteBuf := make([]byte, 0, len(suite)*4+2)
  66. suiteBuf = be.AppendUint16(suiteBuf, uint16(len(suite))*4)
  67. for _, s := range suite {
  68. if !s.kdf.IsValid() || !s.aead.IsValid() {
  69. return nil, E.New("invalid HPKE cipher suite")
  70. }
  71. suiteBuf = be.AppendUint16(suiteBuf, uint16(s.kdf))
  72. suiteBuf = be.AppendUint16(suiteBuf, uint16(s.aead))
  73. }
  74. pairs := []echKeyConfigPair{}
  75. for _, c := range conf {
  76. pair := echKeyConfigPair{}
  77. pair.id = c.id
  78. pair.conf = c
  79. if !c.kem.IsValid() {
  80. return nil, E.New("invalid HPKE KEM")
  81. }
  82. kpGenerator := c.kem.Scheme().GenerateKeyPair
  83. if len(c.seed) > 0 {
  84. kpGenerator = func() (kem.PublicKey, kem.PrivateKey, error) {
  85. pub, sec := c.kem.Scheme().DeriveKeyPair(c.seed)
  86. return pub, sec, nil
  87. }
  88. if len(c.seed) < c.kem.Scheme().PrivateKeySize() {
  89. return nil, E.New("HPKE KEM seed too short")
  90. }
  91. }
  92. pub, sec, err := kpGenerator()
  93. if err != nil {
  94. return nil, E.Cause(err, "generate ECH config key pair")
  95. }
  96. b := []byte{}
  97. b = be.AppendUint16(b, version)
  98. b = be.AppendUint16(b, 0) // length field
  99. // contents
  100. // key config
  101. b = append(b, c.id)
  102. b = be.AppendUint16(b, uint16(c.kem))
  103. pubBuf, err := pub.MarshalBinary()
  104. if err != nil {
  105. return nil, E.Cause(err, "serialize ECH public key")
  106. }
  107. b = be.AppendUint16(b, uint16(len(pubBuf)))
  108. b = append(b, pubBuf...)
  109. b = append(b, suiteBuf...)
  110. // end key config
  111. // max name len, not supported
  112. b = append(b, 0)
  113. // server name
  114. b = append(b, byte(len(serverName)))
  115. b = append(b, []byte(serverName)...)
  116. // extensions, not supported
  117. b = be.AppendUint16(b, 0)
  118. be.PutUint16(b[2:], uint16(len(b)-4))
  119. pair.rawConf = b
  120. secBuf, err := sec.MarshalBinary()
  121. if err != nil {
  122. return nil, E.Cause(err, "serialize ECH private key")
  123. }
  124. sk := []byte{}
  125. sk = be.AppendUint16(sk, uint16(len(secBuf)))
  126. sk = append(sk, secBuf...)
  127. sk = be.AppendUint16(sk, uint16(len(b)))
  128. sk = append(sk, b...)
  129. pair.rawKey = sk
  130. pairs = append(pairs, pair)
  131. }
  132. return pairs, nil
  133. }