Giter VIP home page Giter VIP logo

Comments (4)

daenney avatar daenney commented on August 29, 2024

Hiya! Thanks for raising this. I think this makes a lot of sense. I'd like to retain the "pass key directly" functionality though since that's what everyone is already using and is a very common way to use the tls library from stdlib too.

But I'm happy for something like this to be added and be tried before falling back to whatever may have been passed in the config for the raw key.

from dtls.

salrashid123 avatar salrashid123 commented on August 29, 2024

got it, yeah adding the Signer capability is what i meant (vs breaking change)

fwiw, if i'm not mistaken, even the privatekeys implements Singer too so there maybe a path to converge/collapse internally


and fyi, atleast in go, the tls negotations uses SignatureAlgorithm: x509.SHA256WithRSAPSS for TLS but that'll be the responsiblity of the Signer thats passed (eg, for tpm singer i have (atleast for tls1.3 which i do't know even applies here)

from dtls.

Sean-Der avatar Sean-Der commented on August 29, 2024

Hey @salrashid123 could I get your help on this? I am going to start working on a new major release and want to address all API breaks.

Do you have a suggested API/have any pseudo-code?

from dtls.

salrashid123 avatar salrashid123 commented on August 29, 2024

hi-

i'm not at all familiar with how the API is composed is used in practice (i just used it for a pretty odd reason) but maybe able help in other ways.

i did reverse the code in the library as-is to plumb through a signer ..it just involved mashing crypto.Singer with crypto.PrivateKey and what not ...meaning what i got below is just that...a hack so please look at it for ideas on what maybe much more appropriate for the new release

the current lbirary allows you to pass a tls.Certificates through Config. the hack involved constructing a certificate where the private key is actually a crypto.signer and the cert was generated itself using that same tpm-backed signer. Basicallly the certificate is backed by a TPM.

i did an override of selfsign test application to plumb through the signer from go-tpm-tools.client.GetSigner()

the diff below are the changes

i use a software tpm to save an rsa and ecc key and then get its crypto.Signer...but you can use any signer

rm -rf /tmp/myvtpm
mkdir /tmp/myvtpm
sudo swtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear

export TPM2TOOLS_TCTI="swtpm:port=2321"
tpm2_pcrread sha256:23

## create primary
tpm2_flushcontext -t
tpm2_createprimary -C o -c primary.ctx

### ecc
tpm2_create -G ecc256:ecdsa -g sha256 -u ecc.pub -r ecc.priv -C primary.ctx
tpm2_flushcontext -t
tpm2_load -C primary.ctx -u ecc.pub -r ecc.priv -c ecc.ctx
tpm2_evictcontrol -C o -c ecc.ctx 0x81008000
tpm2_flushcontext -t

## rsassa
tpm2_create -G rsa2048:rsassa:null -g sha256 -u rsassa.pub -r rsassa.priv -C primary.ctx
tpm2_flushcontext -t
tpm2_load -C primary.ctx -u rsassa.pub -r rsassa.priv -c rsassa.ctx
tpm2_evictcontrol -C o -c rsassa.ctx 0x81008002
tpm2_flushcontext -t
diff --git a/cipher_suite.go b/cipher_suite.go
index 6f7015c..11fde92 100644
--- a/cipher_suite.go
+++ b/cipher_suite.go
@@ -4,6 +4,7 @@
 package dtls
 
 import (
+	"crypto"
 	"crypto/ecdsa"
 	"crypto/ed25519"
 	"crypto/rsa"
@@ -264,6 +265,16 @@ func filterCipherSuitesForCertificate(cert *tls.Certificate, cipherSuites []Ciph
 		certType = clientcertificate.ECDSASign
 	case *rsa.PrivateKey:
 		certType = clientcertificate.RSASign
+	case crypto.Signer:
+		s := cert.PrivateKey.(crypto.Signer).Public()
+		switch s.(type) {
+		case ed25519.PublicKey:
+			certType = clientcertificate.ECDSASign
+		case *ecdsa.PublicKey:
+			certType = clientcertificate.ECDSASign
+		case *rsa.PublicKey:
+			certType = clientcertificate.RSASign
+		}
 	}
 
 	filtered := []CipherSuite{}
diff --git a/config.go b/config.go
index d765ecd..51ef72a 100644
--- a/config.go
+++ b/config.go
@@ -5,6 +5,7 @@ package dtls
 
 import (
 	"context"
+	"crypto"
 	"crypto/ecdsa"
 	"crypto/ed25519"
 	"crypto/rsa"
@@ -280,6 +281,7 @@ func validateConfig(config *Config) error {
 			case ed25519.PrivateKey:
 			case *ecdsa.PrivateKey:
 			case *rsa.PrivateKey:
+			case crypto.Signer:
 			default:
 				return errInvalidPrivateKey
 			}
diff --git a/crypto.go b/crypto.go
index 7b01002..1d84e37 100644
--- a/crypto.go
+++ b/crypto.go
@@ -55,6 +55,14 @@ func generateKeySignature(clientRandom, serverRandom, publicKey []byte, namedCur
 	case *rsa.PrivateKey:
 		hashed := hashAlgorithm.Digest(msg)
 		return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
+	case crypto.Signer:
+		hashed := hashAlgorithm.Digest(msg)
+		// if using rsapss and TPM
+		// return p.Sign(rand.Reader, hashed, &rsa.PSSOptions{
+		// 	Hash:       hashAlgorithm.CryptoHash(),
+		// 	SaltLength: rsa.PSSSaltLengthAuto,
+		// })
+		return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
 	}
 
 	return nil, errKeySignatureGenerateUnimplemented
@@ -93,6 +101,12 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A
 		case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
 			hashed := hashAlgorithm.Digest(message)
 			return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature)
+		// case x509.SHA256WithRSAPSS:
+		// 	hashed := hashAlgorithm.Digest(message)
+		// 	//if TPM, use rsa.PSSSaltLengthAuto
+		// 	return rsa.VerifyPSS(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature, &rsa.PSSOptions{
+		// 		SaltLength: rsa.PSSSaltLengthAuto,
+		// 	})
 		default:
 			return errKeySignatureVerifyUnimplemented
 		}
@@ -123,6 +137,11 @@ func generateCertificateVerify(handshakeBodies []byte, privateKey crypto.Private
 	case *ecdsa.PrivateKey:
 		return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
 	case *rsa.PrivateKey:
+		// if using rsapss and TPM
+		// return p.Sign(rand.Reader, hashed, &rsa.PSSOptions{
+		// 	Hash:       hashAlgorithm.CryptoHash(),
+		// 	SaltLength: rsa.PSSSaltLengthAuto,
+		// })
 		return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
 	}
 
@@ -162,6 +181,12 @@ func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorith
 		case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
 			hash := hashAlgorithm.Digest(handshakeBodies)
 			return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hash, remoteKeySignature)
+		// case x509.SHA256WithRSAPSS:
+		// 	hashed := hashAlgorithm.Digest(handshakeBodies)
+		// 	//if using rsapss and TPM
+		// 	return rsa.VerifyPSS(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature, &rsa.PSSOptions{
+		// 		SaltLength: rsa.PSSSaltLengthAuto,
+		// 	})
 		default:
 			return errKeySignatureVerifyUnimplemented
 		}
diff --git a/examples/listen/selfsign/main.go b/examples/listen/selfsign/main.go
index 025b667..2332935 100644
--- a/examples/listen/selfsign/main.go
+++ b/examples/listen/selfsign/main.go
@@ -8,20 +8,63 @@ import (
 	"context"
 	"crypto/tls"
 	"fmt"
+	"io"
+	"log"
 	"net"
+	"slices"
 	"time"
 
+	"github.com/google/go-tpm-tools/client"
+	"github.com/google/go-tpm-tools/simulator"
+	"github.com/google/go-tpm/tpmutil"
 	"github.com/pion/dtls/v2"
 	"github.com/pion/dtls/v2/examples/util"
 	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
 )
 
+var TPMDEVICES = []string{"/dev/tpm0", "/dev/tpmrm0"}
+
+func OpenTPM(path string) (io.ReadWriteCloser, error) {
+	if slices.Contains(TPMDEVICES, path) {
+		return tpmutil.OpenTPM(path)
+	} else if path == "simulator" {
+		return simulator.GetWithFixedSeedInsecure(1073741825)
+	} else {
+		return net.Dial("tcp", path)
+	}
+}
+
+const (
+	tpmPath = "127.0.0.1:2321"
+)
+
 func main() {
 	// Prepare the IP to connect to
 	addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444}
 
+	var err error
+	rwc, err := OpenTPM(tpmPath)
+	if err != nil {
+		log.Fatalf("can't open TPM %q: %v", tpmPath, err)
+	}
+	defer func() {
+		rwc.Close()
+	}()
+
+	k, err := client.LoadCachedKey(rwc, tpmutil.Handle(0x81008000), nil) // ecc
+	//k, err := client.LoadCachedKey(rwc, tpmutil.Handle(0x81008001), nil) // rsapss
+	//k, err := client.LoadCachedKey(rwc, tpmutil.Handle(0x81008002), nil) // rsassa
+	util.Check(err)
+
+	signer, err := k.GetSigner()
+	util.Check(err)
+
+	// privatekey also implements signer
+	// signer, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	// util.Check(err)
+
 	// Generate a certificate and private key to secure the connection
-	certificate, genErr := selfsign.GenerateSelfSigned()
+	certificate, genErr := selfsign.GenerateSelfSignedSigner(signer)
 	util.Check(genErr)
 
 	// Create parent context to cleanup handshaking connections on exit.
diff --git a/go.mod b/go.mod
index dfaff6f..e4b9eda 100644
--- a/go.mod
+++ b/go.mod
@@ -1,10 +1,27 @@
 module github.com/pion/dtls/v2
 
 require (
+	github.com/google/go-tpm v0.9.0
+	github.com/google/go-tpm-tools v0.4.4
 	github.com/pion/logging v0.2.2
 	github.com/pion/transport/v3 v3.0.2
+	github.com/salrashid123/signer/tpm v0.0.0-20240520114507-7047274c22ce
 	golang.org/x/crypto v0.23.0
 	golang.org/x/net v0.25.0
 )
 
+require (
+	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/google/go-configfs-tsm v0.2.2 // indirect
+	github.com/google/go-sev-guest v0.9.3 // indirect
+	github.com/google/go-tdx-guest v0.3.1 // indirect
+	github.com/google/logger v1.1.1 // indirect
+	github.com/google/uuid v1.3.1 // indirect
+	github.com/pborman/uuid v1.2.1 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	go.uber.org/multierr v1.11.0 // indirect
+	golang.org/x/sys v0.20.0 // indirect
+	google.golang.org/protobuf v1.31.0 // indirect
+)
+
 go 1.19
diff --git a/go.sum b/go.sum
index b6153ae..87c4454 100644
--- a/go.sum
+++ b/go.sum
@@ -1,10 +1,41 @@
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/certificate-transparency-go v1.1.2 h1:4hE0GEId6NAW28dFpC+LrRGwQX5dtmXQGDbg8+/MZOM=
+github.com/google/go-attestation v0.5.0 h1:jXtAWT2sw2Yu8mYU0BC7FDidR+ngxFPSE+pl6IUu3/0=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-configfs-tsm v0.2.2 h1:YnJ9rXIOj5BYD7/0DNnzs8AOp7UcvjfTvt215EWcs98=
+github.com/google/go-configfs-tsm v0.2.2/go.mod h1:EL1GTDFMb5PZQWDviGfZV9n87WeGTR/JUg13RfwkgRo=
+github.com/google/go-sev-guest v0.9.3 h1:GOJ+EipURdeWFl/YYdgcCxyPeMgQUWlI056iFkBD8UU=
+github.com/google/go-sev-guest v0.9.3/go.mod h1:hc1R4R6f8+NcJwITs0L90fYWTsBpd1Ix+Gur15sqHDs=
+github.com/google/go-tdx-guest v0.3.1 h1:gl0KvjdsD4RrJzyLefDOvFOUH3NAJri/3qvaL5m83Iw=
+github.com/google/go-tdx-guest v0.3.1/go.mod h1:/rc3d7rnPykOPuY8U9saMyEps0PZDThLk/RygXm04nE=
+github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
+github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
+github.com/google/go-tpm-tools v0.4.4 h1:oiQfAIkc6xTy9Fl5NKTeTJkBTlXdHsxAofmQyxBKY98=
+github.com/google/go-tpm-tools v0.4.4/go.mod h1:T8jXkp2s+eltnCDIsXR84/MTcVU9Ja7bh3Mit0pa4AY=
+github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus=
+github.com/google/logger v1.1.1 h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ=
+github.com/google/logger v1.1.1/go.mod h1:BkeJZ+1FhQ+/d087r4dzojEg1u2ZX+ZqG1jTUrLM+zQ=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
+github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
 github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
 github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4=
 github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/salrashid123/signer/tpm v0.0.0-20240520114507-7047274c22ce h1:68WgsglS7fRWMvXuEBXCvd8KJ4fZCtJlwxdmvYZA4WQ=
+github.com/salrashid123/signer/tpm v0.0.0-20240520114507-7047274c22ce/go.mod h1:D1+aHT/KM+rEbyPaAyc2j7k177ZRx26bShZqzXlALFU=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -12,8 +43,11 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
@@ -36,6 +70,7 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -43,6 +78,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -60,6 +97,12 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/pkg/crypto/selfsign/selfsign.go b/pkg/crypto/selfsign/selfsign.go
index 6ef0167..4227019 100644
--- a/pkg/crypto/selfsign/selfsign.go
+++ b/pkg/crypto/selfsign/selfsign.go
@@ -46,6 +46,86 @@ func SelfSign(key crypto.PrivateKey) (tls.Certificate, error) {
 	return WithDNS(key, "self-signed cert")
 }
 
+func GenerateSelfSignedSigner(priv crypto.Signer) (tls.Certificate, error) {
+	return SelfWithSigner(priv)
+}
+
+func SelfWithSigner(key crypto.Signer) (tls.Certificate, error) {
+	return WithDNSSigner(key, "self-signed cert")
+}
+
+// WithDNS creates a self-signed certificate from a elliptic curve key
+func WithDNSSigner(key crypto.Signer, cn string, sans ...string) (tls.Certificate, error) {
+	var (
+		pubKey    crypto.PublicKey
+		maxBigInt = new(big.Int) // Max random value, a 130-bits integer, i.e 2^130 - 1
+	)
+
+	k := key.Public()
+	switch k.(type) {
+	case ed25519.PublicKey:
+		pubKey = k
+	case *ecdsa.PublicKey:
+		pubKey = k
+	case *rsa.PublicKey:
+		pubKey = k
+	default:
+		return tls.Certificate{}, errInvalidPrivateKey
+	}
+
+	/* #nosec */
+	maxBigInt.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(maxBigInt, big.NewInt(1))
+	/* #nosec */
+	serialNumber, err := rand.Int(rand.Reader, maxBigInt)
+	if err != nil {
+		return tls.Certificate{}, err
+	}
+
+	names := []string{cn}
+	names = append(names, sans...)
+
+	keyUsage := x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign
+	if _, isRSA := key.(*rsa.PrivateKey); isRSA {
+		keyUsage |= x509.KeyUsageKeyEncipherment
+	}
+
+	template := x509.Certificate{
+		ExtKeyUsage: []x509.ExtKeyUsage{
+			x509.ExtKeyUsageClientAuth,
+			x509.ExtKeyUsageServerAuth,
+		},
+		BasicConstraintsValid: true,
+		NotBefore:             time.Now(),
+		KeyUsage:              keyUsage,
+		NotAfter:              time.Now().AddDate(0, 1, 0),
+		SerialNumber:          serialNumber,
+		Version:               2,
+		IsCA:                  true,
+		DNSNames:              names,
+		Subject: pkix.Name{
+			CommonName: cn,
+		},
+		// w/ rsapss
+		//SignatureAlgorithm: x509.SHA256WithRSAPSS,
+	}
+
+	raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey, key)
+	if err != nil {
+		return tls.Certificate{}, err
+	}
+
+	leaf, err := x509.ParseCertificate(raw)
+	if err != nil {
+		return tls.Certificate{}, err
+	}
+
+	return tls.Certificate{
+		Certificate: [][]byte{raw},
+		PrivateKey:  key,
+		Leaf:        leaf,
+	}, nil
+}
+
 // WithDNS creates a self-signed certificate from a elliptic curve key
 func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate, error) {
 	var (
diff --git a/pkg/crypto/signaturehash/signaturehash.go b/pkg/crypto/signaturehash/signaturehash.go
index 2561acc..68e6bcb 100644
--- a/pkg/crypto/signaturehash/signaturehash.go
+++ b/pkg/crypto/signaturehash/signaturehash.go
@@ -57,6 +57,18 @@ func (a *Algorithm) isCompatible(privateKey crypto.PrivateKey) bool {
 		return a.Signature == signature.ECDSA
 	case *rsa.PrivateKey:
 		return a.Signature == signature.RSA
+	case crypto.Signer:
+		s := privateKey.(crypto.Signer).Public()
+		switch s.(type) {
+		case ed25519.PublicKey:
+			return a.Signature == signature.Ed25519
+		case *ecdsa.PublicKey:
+			return a.Signature == signature.ECDSA
+		case *rsa.PublicKey:
+			return a.Signature == signature.RSA
+		default:
+			return false
+		}
 	default:
 		return false
 	}

from dtls.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.