crypto/tls: support X25519.

X25519 (RFC 7748) is now commonly used for key agreement in TLS
connections, as specified in
https://tools.ietf.org/html/draft-ietf-tls-curve25519-01.

This change adds support for that in crypto/tls, but does not enabled it
by default so that there's less test noise. A future change will enable
it by default and will update all the test data at the same time.

Change-Id: I91802ecd776d73aae5c65bcb653d12e23c413ed4
Reviewed-on: https://go-review.googlesource.com/30824
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Adam Langley 2016-10-10 18:23:37 -07:00
parent 8c74139cad
commit 8a11cb318f
7 changed files with 303 additions and 44 deletions

View file

@ -95,6 +95,7 @@ const (
CurveP256 CurveID = 23
CurveP384 CurveID = 24
CurveP521 CurveID = 25
X25519 CurveID = 29
)
// TLS Elliptic Curve Point Formats

View file

@ -537,6 +537,19 @@ func TestHandshakeClientECDHEECDSAAES128CBCSHA256(t *testing.T) {
runClientTestTLS12(t, test)
}
func TestHandshakeClientX25519(t *testing.T) {
config := testConfig.Clone()
config.CurvePreferences = []CurveID{X25519}
test := &clientTest{
name: "X25519-ECDHE-RSA-AES-GCM",
command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES128-GCM-SHA256"},
config: config,
}
runClientTestTLS12(t, test)
}
func TestHandshakeClientCertRSA(t *testing.T) {
config := testConfig.Clone()
cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM))

View file

@ -749,6 +749,18 @@ func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
runServerTestTLS12(t, test)
}
func TestHandshakeServerX25519(t *testing.T) {
config := testConfig.Clone()
config.CurvePreferences = []CurveID{X25519}
test := &serverTest{
name: "X25519-ECDHE-RSA-AES-GCM",
command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-AES128-GCM-SHA256"},
config: config,
}
runServerTestTLS12(t, test)
}
func TestHandshakeServerALPN(t *testing.T) {
config := testConfig.Clone()
config.NextProtos = []string{"proto1", "proto2"}

View file

@ -16,6 +16,8 @@ import (
"errors"
"io"
"math/big"
"golang_org/x/crypto/curve25519"
)
var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
@ -177,52 +179,71 @@ type ecdheKeyAgreement struct {
version uint16
sigType uint8
privateKey []byte
curve elliptic.Curve
x, y *big.Int
curveid CurveID
// publicKey is used to store the peer's public value when X25519 is
// being used.
publicKey []byte
// x and y are used to store the peer's public value when one of the
// NIST curves is being used.
x, y *big.Int
}
func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
var curveid CurveID
preferredCurves := config.curvePreferences()
NextCandidate:
for _, candidate := range preferredCurves {
for _, c := range clientHello.supportedCurves {
if candidate == c {
curveid = c
ka.curveid = c
break NextCandidate
}
}
}
if curveid == 0 {
if ka.curveid == 0 {
return nil, errors.New("tls: no supported elliptic curves offered")
}
var ok bool
if ka.curve, ok = curveForCurveID(curveid); !ok {
return nil, errors.New("tls: preferredCurves includes unsupported curve")
}
var ecdhePublic []byte
var x, y *big.Int
var err error
ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
if err != nil {
return nil, err
if ka.curveid == X25519 {
var scalar, public [32]byte
if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil {
return nil, err
}
curve25519.ScalarBaseMult(&public, &scalar)
ka.privateKey = scalar[:]
ecdhePublic = public[:]
} else {
curve, ok := curveForCurveID(ka.curveid)
if !ok {
return nil, errors.New("tls: preferredCurves includes unsupported curve")
}
var x, y *big.Int
var err error
ka.privateKey, x, y, err = elliptic.GenerateKey(curve, config.rand())
if err != nil {
return nil, err
}
ecdhePublic = elliptic.Marshal(curve, x, y)
}
ecdhePublic := elliptic.Marshal(ka.curve, x, y)
// http://tools.ietf.org/html/rfc4492#section-5.4
serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
serverECDHParams[0] = 3 // named curve
serverECDHParams[1] = byte(curveid >> 8)
serverECDHParams[2] = byte(curveid)
serverECDHParams[1] = byte(ka.curveid >> 8)
serverECDHParams[2] = byte(ka.curveid)
serverECDHParams[3] = byte(len(ecdhePublic))
copy(serverECDHParams[4:], ecdhePublic)
sigAndHash := signatureAndHash{signature: ka.sigType}
if ka.version >= VersionTLS12 {
var err error
if sigAndHash.hash, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
return nil, err
}
@ -281,15 +302,32 @@ func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Cert
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, errClientKeyExchange
}
x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
if ka.curveid == X25519 {
if len(ckx.ciphertext) != 1+32 {
return nil, errClientKeyExchange
}
var theirPublic, sharedKey, scalar [32]byte
copy(theirPublic[:], ckx.ciphertext[1:])
copy(scalar[:], ka.privateKey)
curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic)
return sharedKey[:], nil
}
curve, ok := curveForCurveID(ka.curveid)
if !ok {
panic("internal error")
}
x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:])
if x == nil {
return nil, errClientKeyExchange
}
if !ka.curve.IsOnCurve(x, y) {
if !curve.IsOnCurve(x, y) {
return nil, errClientKeyExchange
}
x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
x, _ = curve.ScalarMult(x, y, ka.privateKey)
preMasterSecret := make([]byte, (curve.Params().BitSize+7)>>3)
xBytes := x.Bytes()
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
@ -303,31 +341,40 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
if skx.key[0] != 3 { // named curve
return errors.New("tls: server selected unsupported curve")
}
curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
var ok bool
if ka.curve, ok = curveForCurveID(curveid); !ok {
return errors.New("tls: server selected unsupported curve")
}
ka.curveid = CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
publicLen := int(skx.key[3])
if publicLen+4 > len(skx.key) {
return errServerKeyExchange
}
ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
if ka.x == nil {
return errServerKeyExchange
}
if !ka.curve.IsOnCurve(ka.x, ka.y) {
return errServerKeyExchange
}
serverECDHParams := skx.key[:4+publicLen]
publicKey := serverECDHParams[4:]
sig := skx.key[4+publicLen:]
if len(sig) < 2 {
return errServerKeyExchange
}
if ka.curveid == X25519 {
if len(publicKey) != 32 {
return errors.New("tls: bad X25519 public value")
}
ka.publicKey = publicKey
} else {
curve, ok := curveForCurveID(ka.curveid)
if !ok {
return errors.New("tls: server selected unsupported curve")
}
ka.x, ka.y = elliptic.Unmarshal(curve, publicKey)
if ka.x == nil {
return errServerKeyExchange
}
if !curve.IsOnCurve(ka.x, ka.y) {
return errServerKeyExchange
}
}
sigAndHash := signatureAndHash{signature: ka.sigType}
if ka.version >= VersionTLS12 {
// handle SignatureAndHashAlgorithm
@ -382,19 +429,40 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
}
func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
if ka.curve == nil {
if ka.curveid == 0 {
return nil, nil, errors.New("tls: missing ServerKeyExchange message")
}
priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
if err != nil {
return nil, nil, err
}
x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
xBytes := x.Bytes()
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
serialized := elliptic.Marshal(ka.curve, mx, my)
var serialized, preMasterSecret []byte
if ka.curveid == X25519 {
var ourPublic, theirPublic, sharedKey, scalar [32]byte
if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil {
return nil, nil, err
}
copy(theirPublic[:], ka.publicKey)
curve25519.ScalarBaseMult(&ourPublic, &scalar)
curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic)
serialized = ourPublic[:]
preMasterSecret = sharedKey[:]
} else {
curve, ok := curveForCurveID(ka.curveid)
if !ok {
panic("internal error")
}
priv, mx, my, err := elliptic.GenerateKey(curve, config.rand())
if err != nil {
return nil, nil, err
}
x, _ := curve.ScalarMult(ka.x, ka.y, priv)
preMasterSecret = make([]byte, (curve.Params().BitSize+7)>>3)
xBytes := x.Bytes()
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
serialized = elliptic.Marshal(curve, mx, my)
}
ckx := new(clientKeyExchangeMsg)
ckx.ciphertext = make([]byte, 1+len(serialized))

View file

@ -0,0 +1,85 @@
>>> Flow 1 (client to server)
00000000 16 03 01 00 87 01 00 00 83 03 03 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 28 c0 2f |.............(./|
00000030 c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 c0 09 c0 14 |.+.0.,.'...#....|
00000040 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 c0 12 00 0a |.......<./.5....|
00000050 00 05 c0 11 c0 07 01 00 00 32 00 05 00 05 01 00 |.........2......|
00000060 00 00 00 00 0a 00 04 00 02 00 1d 00 0b 00 02 01 |................|
00000070 00 00 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 |................|
00000080 01 02 03 ff 01 00 01 00 00 12 00 00 |............|
>>> Flow 2 (server to client)
00000000 16 03 03 00 59 02 00 00 55 03 03 64 2f 20 bb e0 |....Y...U..d/ ..|
00000010 0c 8b 1e d9 fc 96 1d d7 66 02 62 bd 63 d8 52 48 |........f.b.c.RH|
00000020 61 6d 4e f9 e4 26 43 f2 dd 75 00 20 e9 7d 2b 02 |amN..&C..u. .}+.|
00000030 39 df 15 b7 24 c8 7a 61 81 cc a4 3a 3f 80 36 e2 |9...$.za...:?.6.|
00000040 44 fd cd e1 a8 db ad a0 79 2d d3 f6 c0 2f 00 00 |D.......y-.../..|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
000002c0 ac 0c 00 00 a8 03 00 1d 20 27 08 d8 54 80 58 52 |........ '..T.XR|
000002d0 fa d3 4e ba 1a 49 7b 20 b7 c3 c8 dc 91 42 90 9a |..N..I{ .....B..|
000002e0 7d 63 b7 88 16 39 6b 2f 4a 04 01 00 80 97 3b 72 |}c...9k/J.....;r|
000002f0 f0 94 ef 26 07 b9 37 f5 6a 00 30 34 1f b8 90 46 |...&..7.j.04...F|
00000300 fc 36 9b 19 9c de 60 c1 9a da 8e a0 94 d5 f9 d8 |.6....`.........|
00000310 aa f0 c4 7a 3e 0a 55 9e 97 bd 27 09 77 20 a7 72 |...z>.U...'.w .r|
00000320 bc a0 46 75 96 ab 0b 42 2c 24 06 eb ee 5a 07 cc |..Fu...B,$...Z..|
00000330 94 42 25 57 d9 ad a6 ae 28 fe 94 c8 bc ca a8 e0 |.B%W....(.......|
00000340 9e 18 b0 f2 b5 b5 93 a7 a0 20 17 7e 18 ac 8f cf |......... .~....|
00000350 30 ea fd e8 43 25 c1 fc 48 51 5a d2 ef b5 95 13 |0...C%..HQZ.....|
00000360 6c 37 5a 6b 55 34 8d b0 3c 8f 9e 1b e8 16 03 03 |l7ZkU4..<.......|
00000370 00 04 0e 00 00 00 |......|
>>> Flow 3 (client to server)
00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 17 40 ca |....(.........@.|
00000040 78 e3 f2 c9 05 71 6b 37 98 79 21 d0 b1 e1 49 b5 |x....qk7.y!...I.|
00000050 54 45 35 e9 58 bd f9 60 5f c8 16 e7 42 |TE5.X..`_...B|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 28 2d d9 e6 e1 eb |..........(-....|
00000010 b7 65 e5 f4 fc 56 4a 35 00 0c 90 bf 5f c3 73 dc |.e...VJ5...._.s.|
00000020 86 f8 44 2c c7 18 fd ca 24 f6 34 98 5e ef 25 44 |..D,....$.4.^.%D|
00000030 41 74 4a |AtJ|
>>> Flow 5 (client to server)
00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 84 48 a7 |..............H.|
00000010 d1 2e f0 75 1a da f9 d4 bc 88 42 e0 8c 68 09 ae |...u......B..h..|
00000020 0a ac 46 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..F.............|
00000030 0b fb c3 cb 27 17 0c 35 e9 8f 8f 96 dd ce d5 5d |....'..5.......]|
00000040 42 44 |BD|

View file

@ -0,0 +1,79 @@
>>> Flow 1 (client to server)
00000000 16 03 01 00 73 01 00 00 6f 03 03 c5 04 fb 19 85 |....s...o.......|
00000010 7c 1d 96 0a 68 50 5d f9 03 4d be d6 62 e0 ba 08 ||...hP]..M..b...|
00000020 8e 36 d5 4e ed ed 1a 63 72 eb 94 00 00 04 c0 2f |.6.N...cr....../|
00000030 00 ff 01 00 00 42 00 0b 00 04 03 00 01 02 00 0a |.....B..........|
00000040 00 0a 00 08 00 1d 00 17 00 19 00 18 00 0d 00 20 |............... |
00000050 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 |................|
00000060 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 |................|
00000070 00 16 00 00 00 17 00 00 |........|
>>> Flow 2 (server to client)
00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 2f 00 00 |............./..|
00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
00000290 3b e9 fa e7 16 03 03 00 ac 0c 00 00 a8 03 00 1d |;...............|
000002a0 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 | /.}.G.bC.(.._.)|
000002b0 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b |.0.........._X.;|
000002c0 74 05 01 00 80 93 b5 4c a5 01 aa c4 dd ab de 51 |t......L.......Q|
000002d0 16 79 81 b3 61 06 88 4c 56 4f ad 10 89 a4 95 62 |.y..a..LVO.....b|
000002e0 4e be bb c0 a2 13 31 1d 29 aa c1 d4 c5 ac b1 39 |N.....1.)......9|
000002f0 9d 23 07 ba b9 a1 5e 00 ed e2 32 bb 2b 7c 7f e8 |.#....^...2.+|..|
00000300 81 c0 bf 22 6a 99 e7 1a f8 88 08 80 ba e3 2d c6 |..."j.........-.|
00000310 64 7b c6 f1 c5 3f 86 a8 0d 61 bb df 46 43 b2 72 |d{...?...a..FC.r|
00000320 4f ef 00 13 15 d1 4a 5d 66 82 88 76 26 b8 9f ee |O.....J]f..v&...|
00000330 c5 fb 39 55 16 11 79 3e ef 52 80 b7 3e 8f 0d 9f |..9U..y>.R..>...|
00000340 59 6a 23 1a 75 16 03 03 00 04 0e 00 00 00 |Yj#.u.........|
>>> Flow 3 (client to server)
00000000 16 03 03 00 25 10 00 00 21 20 c5 a2 cd 04 66 cf |....%...! ....f.|
00000010 18 3a c6 55 7c 23 87 f2 e9 1e 08 d1 77 17 1d ee |.:.U|#......w...|
00000020 ea 46 48 b2 f1 a6 00 90 d0 0b 14 03 03 00 01 01 |.FH.............|
00000030 16 03 03 00 28 f6 13 89 ff 83 6a 6f 2c 9e d4 49 |....(.....jo,..I|
00000040 0d 1b 28 68 00 e4 fb f7 61 a3 e6 61 c7 12 1d 87 |..(h....a..a....|
00000050 65 23 77 0a 47 fe 82 74 09 1b c1 05 e7 |e#w.G..t.....|
>>> Flow 4 (server to client)
00000000 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....|
00000010 00 00 00 e3 14 42 2a 28 3c 8a df 74 1a 4f 13 b1 |.....B*(<..t.O..|
00000020 d8 ec a5 bb 26 02 b1 a9 70 8c e3 81 30 ba 87 c5 |....&...p...0...|
00000030 45 bf a5 17 03 03 00 25 00 00 00 00 00 00 00 01 |E......%........|
00000040 29 8f bb c2 42 f4 40 61 d5 fe 04 87 a6 5f 0e 2d |)...B.@a....._.-|
00000050 0c ce 9e 2f d6 df be 10 fe 3d 4f d4 72 15 03 03 |.../.....=O.r...|
00000060 00 1a 00 00 00 00 00 00 00 02 55 da b5 79 7b 1e |..........U..y{.|
00000070 be e0 d2 83 40 6f 0c 38 83 a5 6e bd |....@o.8..n.|

View file

@ -333,6 +333,7 @@ var pkgDeps = map[string][]string{
"crypto/sha1",
"crypto/sha256",
"crypto/sha512",
"golang_org/x/crypto/curve25519",
},
// Random byte, number generation.