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>tls13
@@ -95,6 +95,7 @@ const ( | |||||
CurveP256 CurveID = 23 | CurveP256 CurveID = 23 | ||||
CurveP384 CurveID = 24 | CurveP384 CurveID = 24 | ||||
CurveP521 CurveID = 25 | CurveP521 CurveID = 25 | ||||
X25519 CurveID = 29 | |||||
) | ) | ||||
// TLS Elliptic Curve Point Formats | // TLS Elliptic Curve Point Formats | ||||
@@ -537,6 +537,19 @@ func TestHandshakeClientECDHEECDSAAES128CBCSHA256(t *testing.T) { | |||||
runClientTestTLS12(t, test) | 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) { | func TestHandshakeClientCertRSA(t *testing.T) { | ||||
config := testConfig.Clone() | config := testConfig.Clone() | ||||
cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM)) | cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM)) | ||||
@@ -749,6 +749,18 @@ func TestHandshakeServerECDHEECDSAAES(t *testing.T) { | |||||
runServerTestTLS12(t, test) | 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) { | func TestHandshakeServerALPN(t *testing.T) { | ||||
config := testConfig.Clone() | config := testConfig.Clone() | ||||
config.NextProtos = []string{"proto1", "proto2"} | config.NextProtos = []string{"proto1", "proto2"} | ||||
@@ -16,6 +16,8 @@ import ( | |||||
"errors" | "errors" | ||||
"io" | "io" | ||||
"math/big" | "math/big" | ||||
"golang_org/x/crypto/curve25519" | |||||
) | ) | ||||
var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message") | var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message") | ||||
@@ -177,52 +179,71 @@ type ecdheKeyAgreement struct { | |||||
version uint16 | version uint16 | ||||
sigType uint8 | sigType uint8 | ||||
privateKey []byte | 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) { | func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { | ||||
var curveid CurveID | |||||
preferredCurves := config.curvePreferences() | preferredCurves := config.curvePreferences() | ||||
NextCandidate: | NextCandidate: | ||||
for _, candidate := range preferredCurves { | for _, candidate := range preferredCurves { | ||||
for _, c := range clientHello.supportedCurves { | for _, c := range clientHello.supportedCurves { | ||||
if candidate == c { | if candidate == c { | ||||
curveid = c | |||||
ka.curveid = c | |||||
break NextCandidate | break NextCandidate | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if curveid == 0 { | |||||
if ka.curveid == 0 { | |||||
return nil, errors.New("tls: no supported elliptic curves offered") | 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 | // http://tools.ietf.org/html/rfc4492#section-5.4 | ||||
serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic)) | serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic)) | ||||
serverECDHParams[0] = 3 // named curve | 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)) | serverECDHParams[3] = byte(len(ecdhePublic)) | ||||
copy(serverECDHParams[4:], ecdhePublic) | copy(serverECDHParams[4:], ecdhePublic) | ||||
sigAndHash := signatureAndHash{signature: ka.sigType} | sigAndHash := signatureAndHash{signature: ka.sigType} | ||||
if ka.version >= VersionTLS12 { | if ka.version >= VersionTLS12 { | ||||
var err error | |||||
if sigAndHash.hash, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil { | if sigAndHash.hash, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil { | ||||
return nil, err | 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 { | if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { | ||||
return nil, errClientKeyExchange | 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 { | if x == nil { | ||||
return nil, errClientKeyExchange | return nil, errClientKeyExchange | ||||
} | } | ||||
if !ka.curve.IsOnCurve(x, y) { | |||||
if !curve.IsOnCurve(x, y) { | |||||
return nil, errClientKeyExchange | 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() | xBytes := x.Bytes() | ||||
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) | 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 | if skx.key[0] != 3 { // named curve | ||||
return errors.New("tls: server selected unsupported 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]) | publicLen := int(skx.key[3]) | ||||
if publicLen+4 > len(skx.key) { | if publicLen+4 > len(skx.key) { | ||||
return errServerKeyExchange | 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] | serverECDHParams := skx.key[:4+publicLen] | ||||
publicKey := serverECDHParams[4:] | |||||
sig := skx.key[4+publicLen:] | sig := skx.key[4+publicLen:] | ||||
if len(sig) < 2 { | if len(sig) < 2 { | ||||
return errServerKeyExchange | 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} | sigAndHash := signatureAndHash{signature: ka.sigType} | ||||
if ka.version >= VersionTLS12 { | if ka.version >= VersionTLS12 { | ||||
// handle SignatureAndHashAlgorithm | // 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) { | 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") | 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 := new(clientKeyExchangeMsg) | ||||
ckx.ciphertext = make([]byte, 1+len(serialized)) | ckx.ciphertext = make([]byte, 1+len(serialized)) | ||||
@@ -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| |
@@ -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.| |