@@ -2,12 +2,19 @@ package libp2pwebtransport_test
2
2
3
3
import (
4
4
"context"
5
+ "crypto/ecdsa"
6
+ "crypto/elliptic"
5
7
"crypto/rand"
6
8
"crypto/sha256"
9
+ "crypto/tls"
10
+ "crypto/x509"
11
+ "crypto/x509/pkix"
7
12
"errors"
8
13
"fmt"
9
14
"io"
15
+ "math/big"
10
16
"net"
17
+ "strings"
11
18
"testing"
12
19
"time"
13
20
@@ -64,6 +71,19 @@ func stripCertHashes(addr ma.Multiaddr) ma.Multiaddr {
64
71
}
65
72
}
66
73
74
+ // create a /certhash multiaddr component using the SHA256 of foobar
75
+ func getCerthashComponent (t * testing.T , b []byte ) ma.Multiaddr {
76
+ t .Helper ()
77
+ h := sha256 .Sum256 (b )
78
+ mh , err := multihash .Encode (h [:], multihash .SHA2_256 )
79
+ require .NoError (t , err )
80
+ certStr , err := multibase .Encode (multibase .Base58BTC , mh )
81
+ require .NoError (t , err )
82
+ ha , err := ma .NewComponent (ma .ProtocolWithCode (ma .P_CERTHASH ).Name , certStr )
83
+ require .NoError (t , err )
84
+ return ha
85
+ }
86
+
67
87
func TestTransport (t * testing.T ) {
68
88
serverID , serverKey := newIdentity (t )
69
89
tr , err := libp2pwebtransport .New (serverKey , nil , network .NullResourceManager )
@@ -129,29 +149,11 @@ func TestHashVerification(t *testing.T) {
129
149
require .NoError (t , err )
130
150
defer tr2 .(io.Closer ).Close ()
131
151
132
- // create a hash component using the SHA256 of foobar
133
- h := sha256 .Sum256 ([]byte ("foobar" ))
134
- mh , err := multihash .Encode (h [:], multihash .SHA2_256 )
135
- require .NoError (t , err )
136
- certStr , err := multibase .Encode (multibase .Base58BTC , mh )
137
- require .NoError (t , err )
138
- foobarHash , err := ma .NewComponent (ma .ProtocolWithCode (ma .P_CERTHASH ).Name , certStr )
139
- require .NoError (t , err )
152
+ foobarHash := getCerthashComponent (t , []byte ("foobar" ))
140
153
141
154
t .Run ("fails using only a wrong hash" , func (t * testing.T ) {
142
155
// replace the certificate hash in the multiaddr with a fake hash
143
- addr := ln .Multiaddr ()
144
- // strip off all certhash components
145
- for {
146
- a , comp := ma .SplitLast (addr )
147
- if comp .Protocol ().Code != ma .P_CERTHASH {
148
- break
149
- }
150
- addr = a
151
- }
152
-
153
- addr = addr .Encapsulate (foobarHash )
154
-
156
+ addr := stripCertHashes (ln .Multiaddr ()).Encapsulate (foobarHash )
155
157
_ , err := tr2 .Dial (context .Background (), addr , serverID )
156
158
require .Error (t , err )
157
159
require .Contains (t , err .Error (), "CRYPTO_ERROR (0x12a): cert hash not found" )
@@ -424,3 +426,84 @@ func TestConnectionGaterInterceptSecured(t *testing.T) {
424
426
t .Fatal ("timeout" )
425
427
}
426
428
}
429
+
430
+ func getTLSConf (t * testing.T , ip net.IP , start , end time.Time ) * tls.Config {
431
+ t .Helper ()
432
+ certTempl := & x509.Certificate {
433
+ SerialNumber : big .NewInt (1234 ),
434
+ Subject : pkix.Name {Organization : []string {"webtransport" }},
435
+ NotBefore : start ,
436
+ NotAfter : end ,
437
+ IsCA : true ,
438
+ ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageClientAuth , x509 .ExtKeyUsageServerAuth },
439
+ KeyUsage : x509 .KeyUsageDigitalSignature | x509 .KeyUsageCertSign ,
440
+ BasicConstraintsValid : true ,
441
+ IPAddresses : []net.IP {ip },
442
+ }
443
+ priv , err := ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
444
+ require .NoError (t , err )
445
+ caBytes , err := x509 .CreateCertificate (rand .Reader , certTempl , certTempl , & priv .PublicKey , priv )
446
+ require .NoError (t , err )
447
+ cert , err := x509 .ParseCertificate (caBytes )
448
+ require .NoError (t , err )
449
+ return & tls.Config {
450
+ Certificates : []tls.Certificate {{
451
+ Certificate : [][]byte {cert .Raw },
452
+ PrivateKey : priv ,
453
+ Leaf : cert ,
454
+ }},
455
+ }
456
+ }
457
+
458
+ func TestStaticTLSConf (t * testing.T ) {
459
+ tlsConf := getTLSConf (t , net .ParseIP ("127.0.0.1" ), time .Now (), time .Now ().Add (365 * 24 * time .Hour ))
460
+
461
+ serverID , serverKey := newIdentity (t )
462
+ tr , err := libp2pwebtransport .New (serverKey , nil , network .NullResourceManager , libp2pwebtransport .WithTLSConfig (tlsConf ))
463
+ require .NoError (t , err )
464
+ defer tr .(io.Closer ).Close ()
465
+ ln , err := tr .Listen (ma .StringCast ("/ip4/127.0.0.1/udp/0/quic/webtransport" ))
466
+ require .NoError (t , err )
467
+ defer ln .Close ()
468
+ require .Empty (t , extractCertHashes (ln .Multiaddr ()), "listener address shouldn't contain any certhash" )
469
+
470
+ t .Run ("fails when the certificate is invalid" , func (t * testing.T ) {
471
+ _ , key := newIdentity (t )
472
+ cl , err := libp2pwebtransport .New (key , nil , network .NullResourceManager )
473
+ require .NoError (t , err )
474
+ defer cl .(io.Closer ).Close ()
475
+
476
+ _ , err = cl .Dial (context .Background (), ln .Multiaddr (), serverID )
477
+ require .Error (t , err )
478
+ if ! strings .Contains (err .Error (), "certificate is not trusted" ) &&
479
+ ! strings .Contains (err .Error (), "certificate signed by unknown authority" ) {
480
+ t .Fatalf ("expected a certificate error, got %+v" , err )
481
+ }
482
+ })
483
+
484
+ t .Run ("fails when dialing with a wrong certhash" , func (t * testing.T ) {
485
+ _ , key := newIdentity (t )
486
+ cl , err := libp2pwebtransport .New (key , nil , network .NullResourceManager )
487
+ require .NoError (t , err )
488
+ defer cl .(io.Closer ).Close ()
489
+
490
+ addr := ln .Multiaddr ().Encapsulate (getCerthashComponent (t , []byte ("foo" )))
491
+ _ , err = cl .Dial (context .Background (), addr , serverID )
492
+ require .Error (t , err )
493
+ require .Contains (t , err .Error (), "cert hash not found" )
494
+ })
495
+
496
+ t .Run ("accepts a valid TLS certificate" , func (t * testing.T ) {
497
+ _ , key := newIdentity (t )
498
+ store := x509 .NewCertPool ()
499
+ store .AddCert (tlsConf .Certificates [0 ].Leaf )
500
+ tlsConf := & tls.Config {RootCAs : store }
501
+ cl , err := libp2pwebtransport .New (key , nil , network .NullResourceManager , libp2pwebtransport .WithTLSClientConfig (tlsConf ))
502
+ require .NoError (t , err )
503
+ defer cl .(io.Closer ).Close ()
504
+
505
+ conn , err := cl .Dial (context .Background (), ln .Multiaddr (), serverID )
506
+ require .NoError (t , err )
507
+ defer conn .Close ()
508
+ })
509
+ }
0 commit comments