ech_keygen.go 4.0 KB

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