Repository: pion/dtls
Pull request #183 (2020-02-02 09:04:46)

Unexpose package internal utils
1. Unexpose `Closer`
Make `Closer` internal as it is a package internal utility.
2. Move self sign helper and `CCM` under `pkg/`
They are not parts of DTLS, but useful enough to be exposed.

### Reference issue
Part of #148


codecov-io: # [Codecov](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=h1) Report
> Merging [#183](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=desc) into [master](https://codecov.io/gh/pion/dtls/commit/c9c352a9649817a84dc6c6b1be893c760b30e321?src=pr&el=desc) will **increase** coverage by `0.01%`.
> The diff coverage is `80%`.

[![Impacted file tree graph](https://codecov.io/gh/pion/dtls/pull/183/graphs/tree.svg?width=650&token=bcCB2jB88I&height=150&src=pr)](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #183      +/-   ##
==========================================
+ Coverage    72.6%   72.61%   +0.01%     
==========================================
  Files          60       61       +1     
  Lines        3431     3433       +2     
==========================================
+ Hits         2491     2493       +2     
  Misses        649      649              
  Partials      291      291
```

| Flag | Coverage Δ | |
|---|---|---|
| #go | `72.5% <80%> (-0.11%)` | :arrow_down: |
| #wasm | `68.74% <76%> (+0.01%)` | :arrow_up: |

| [Impacted Files](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/crypto/ccm/ccm.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-cGtnL2NyeXB0by9jY20vY2NtLmdv) | `76.47% <ø> (ø)` | |
| [util.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-dXRpbC5nbw==) | `91.52% <ø> (+4.27%)` | :arrow_up: |
| [crypto\_ccm.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y3J5cHRvX2NjbS5nbw==) | `63.26% <ø> (ø)` | :arrow_up: |
| [internal/closer/closer.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-aW50ZXJuYWwvY2xvc2VyL2Nsb3Nlci5nbw==) | `68.75% <100%> (ø)` | |
| [conn.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y29ubi5nbw==) | `77.5% <60%> (ø)` | :arrow_up: |
| [pkg/crypto/selfsign/selfsign.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-cGtnL2NyeXB0by9zZWxmc2lnbi9zZWxmc2lnbi5nbw==) | `81.39% <81.39%> (ø)` | |
| [client\_handlers.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y2xpZW50X2hhbmRsZXJzLmdv) | `78.7% <0%> (ø)` | :arrow_up: |
| [...pher\_suite\_tls\_ecdhe\_ecdsa\_with\_aes\_256\_cbc\_sha.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y2lwaGVyX3N1aXRlX3Rsc19lY2RoZV9lY2RzYV93aXRoX2Flc18yNTZfY2JjX3NoYS5nbw==) | `81.81% <0%> (ø)` | :arrow_up: |
| [cipher\_suite\_aes\_128\_ccm.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y2lwaGVyX3N1aXRlX2Flc18xMjhfY2NtLmdv) | `81.81% <0%> (ø)` | :arrow_up: |
| [...r\_suite\_tls\_ecdhe\_ecdsa\_with\_aes\_128\_gcm\_sha256.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y2lwaGVyX3N1aXRlX3Rsc19lY2RoZV9lY2RzYV93aXRoX2Flc18xMjhfZ2NtX3NoYTI1Ni5nbw==) | `78.94% <0%> (ø)` | :arrow_up: |
| ... and [1 more](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=footer). Last update [c9c352a...8e61fb0](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

codecov-io: # [Codecov](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=h1) Report
> Merging [#183](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=desc) into [master](https://codecov.io/gh/pion/dtls/commit/c9c352a9649817a84dc6c6b1be893c760b30e321?src=pr&el=desc) will **increase** coverage by `0.01%`.
> The diff coverage is `80%`.

[![Impacted file tree graph](https://codecov.io/gh/pion/dtls/pull/183/graphs/tree.svg?width=650&token=bcCB2jB88I&height=150&src=pr)](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #183      +/-   ##
==========================================
+ Coverage    72.6%   72.61%   +0.01%     
==========================================
  Files          60       61       +1     
  Lines        3431     3433       +2     
==========================================
+ Hits         2491     2493       +2     
  Misses        649      649              
  Partials      291      291
```

| Flag | Coverage Δ | |
|---|---|---|
| #go | `72.5% <80%> (-0.11%)` | :arrow_down: |
| #wasm | `68.74% <76%> (+0.01%)` | :arrow_up: |

| [Impacted Files](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/crypto/ccm/ccm.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-cGtnL2NyeXB0by9jY20vY2NtLmdv) | `76.47% <ø> (ø)` | |
| [util.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-dXRpbC5nbw==) | `91.52% <ø> (+4.27%)` | :arrow_up: |
| [crypto\_ccm.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y3J5cHRvX2NjbS5nbw==) | `63.26% <ø> (ø)` | :arrow_up: |
| [internal/closer/closer.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-aW50ZXJuYWwvY2xvc2VyL2Nsb3Nlci5nbw==) | `68.75% <100%> (ø)` | |
| [conn.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y29ubi5nbw==) | `77.5% <60%> (ø)` | :arrow_up: |
| [pkg/crypto/selfsign/selfsign.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-cGtnL2NyeXB0by9zZWxmc2lnbi9zZWxmc2lnbi5nbw==) | `81.39% <81.39%> (ø)` | |
| [client\_handlers.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y2xpZW50X2hhbmRsZXJzLmdv) | `78.7% <0%> (ø)` | :arrow_up: |
| [...pher\_suite\_tls\_ecdhe\_ecdsa\_with\_aes\_256\_cbc\_sha.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y2lwaGVyX3N1aXRlX3Rsc19lY2RoZV9lY2RzYV93aXRoX2Flc18yNTZfY2JjX3NoYS5nbw==) | `81.81% <0%> (ø)` | :arrow_up: |
| [cipher\_suite\_aes\_128\_ccm.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y2lwaGVyX3N1aXRlX2Flc18xMjhfY2NtLmdv) | `81.81% <0%> (ø)` | :arrow_up: |
| [...r\_suite\_tls\_ecdhe\_ecdsa\_with\_aes\_128\_gcm\_sha256.go](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree#diff-Y2lwaGVyX3N1aXRlX3Rsc19lY2RoZV9lY2RzYV93aXRoX2Flc18xMjhfZ2NtX3NoYTI1Ni5nbw==) | `78.94% <0%> (ø)` | :arrow_up: |
| ... and [1 more](https://codecov.io/gh/pion/dtls/pull/183/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=footer). Last update [c9c352a...8e61fb0](https://codecov.io/gh/pion/dtls/pull/183?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

Sean-Der: Great changes! Maybe someone else can find the `CCM` implementation helpful.

If you get a chance I would update `pion/webrtc` to use the new self-signed stuff. Lots of devs just do `master` for all their libs and then hit breakage when stuff doesn't work :/
daenney: The reason I put CCM in internal is b/c we didn't really write or review the implementation much, though I did add a whole battery of tests. I'm not sure we should make something part of the public interface of this package that wasn't written by us, even though we do use it.
at-wat: Oh, I didn't see the header well.
https://github.com/pion/dtls/blob/0b80bd9abfa64f92945b81c8acd9407d741a50ed/internal/crypto/ccm/ccm.go#L6-L12
Sounds reasonable to keep unexposed.
Users can import the original one if they want.
daenney: I'm fine with exposing it to be honest, it's just more of a question of what our stance on this is given we didn't really write the code. The tests are lifted from the RFC that defines CCM, so from that point of view the implementation is at least correct.

The other issue with the original source is that it hasn't been updated to use Go modules, so it might be nice if we do provide it to the larger ecosystem.
at-wat: @Sean-Der any thoughts?
Sean-Der: @at-wat I don't feel strongly either way, but I support w/e decision you make :)

IMO a healthy project should have churn/changes, so I don't want you to worry too much about changing things!
Sean-Der: @daenney that is awesome I completely forgot you added more tests. 

That feels like a life time you got all the PSK stuff in, it is amazing the impact it caused (making all the CoAP stuff happen in pure Go) :)
daenney: Seems like nobody has strong feelings about CCM, so lets just expose it for now.
at-wat: @daenney @Sean-Der thank you for your comments!
Let me merge this!

Patch:
diff --git a/.golangci.yml b/.golangci.yml
index c625fcc..077186f 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -19,7 +19,7 @@ issues:
   exclude-use-default: false
 
   exclude-rules:
-    - path: internal/crypto/ccm
+    - path: pkg/crypto/ccm
       text: "L' should not be capitalized"
       linters:
         - gocritic
diff --git a/conn.go b/conn.go
index e8e47e7..e38a1c8 100644
--- a/conn.go
+++ b/conn.go
@@ -12,6 +12,7 @@ import (
 	"sync/atomic"
 	"time"
 
+	"github.com/pion/dtls/v2/internal/closer"
 	"github.com/pion/logging"
 )
 
@@ -78,14 +79,14 @@ type Conn struct {
 	handshakeMessageSequence       int
 	handshakeMessageHandler        handshakeMessageHandler
 	flightHandler                  flightHandler
-	handshakeDoneSignal            *Closer
+	handshakeDoneSignal            *closer.Closer
 	handshakeCompletedSuccessfully atomic.Value
 
 	bufferedPackets []*packet
 
-	connectionClosed *Closer      // Closed on connection close and unblock read
-	handshakeErr     *atomicError // Error if one occurred during handshake
-	readErr          *atomicError // Error if one occurred in inboundLoop
+	connectionClosed *closer.Closer // Closed on connection close and unblock read
+	handshakeErr     *atomicError   // Error if one occurred during handshake
+	readErr          *atomicError   // Error if one occurred in inboundLoop
 
 	log logging.LeveledLogger
 }
@@ -131,8 +132,8 @@ func createConn(nextConn net.Conn, flightHandler flightHandler, handshakeMessage
 		mtu = defaultMTU
 	}
 
-	handshakeDoneSignal := NewCloser()
-	connectionClosed := NewCloser()
+	handshakeDoneSignal := closer.NewCloser()
+	connectionClosed := closer.NewCloser()
 
 	c := &Conn{
 		nextConn:                    nextConn,
@@ -258,7 +259,7 @@ func (c *Conn) Read(p []byte) (n int, err error) {
 		if err := c.handshakeErr.load(); err != nil {
 			return err
 		}
-		if c.connectionClosed.ctx.Err() != nil {
+		if c.connectionClosed.Err() != nil {
 			return io.EOF
 		}
 		if err := c.readErr.load(); err != nil {
@@ -296,7 +297,7 @@ func (c *Conn) Write(p []byte) (int, error) {
 	if err := c.handshakeErr.load(); err != nil {
 		return 0, err
 	}
-	if c.connectionClosed.ctx.Err() != nil {
+	if c.connectionClosed.Err() != nil {
 		return 0, ErrConnClosed
 	}
 	if !c.isHandshakeCompletedSuccessfully() {
@@ -745,7 +746,7 @@ func (c *Conn) startHandshakeOutbound() {
 }
 
 func (c *Conn) close() error {
-	if c.connectionClosed.ctx.Err() == nil && c.handshakeErr.load() == nil {
+	if c.connectionClosed.Err() == nil && c.handshakeErr.load() == nil {
 		c.notify(alertLevelFatal, alertCloseNotify) //nolint
 	}
 
diff --git a/crypto_ccm.go b/crypto_ccm.go
index 8f12210..fe84cd1 100644
--- a/crypto_ccm.go
+++ b/crypto_ccm.go
@@ -6,7 +6,7 @@ import (
 	"encoding/binary"
 	"fmt"
 
-	"github.com/pion/dtls/v2/internal/crypto/ccm"
+	"github.com/pion/dtls/v2/pkg/crypto/ccm"
 )
 
 type cryptoCCMTagLen int
diff --git a/examples/dial/main.go b/examples/dial/main.go
index 448dd52..be92b58 100644
--- a/examples/dial/main.go
+++ b/examples/dial/main.go
@@ -8,6 +8,7 @@ import (
 
 	"github.com/pion/dtls/v2"
 	"github.com/pion/dtls/v2/examples/util"
+	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
 )
 
 func main() {
@@ -15,7 +16,7 @@ func main() {
 	addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444}
 
 	// Generate a certificate and private key to secure the connection
-	certificate, genErr := dtls.GenerateSelfSigned()
+	certificate, genErr := selfsign.GenerateSelfSigned()
 	util.Check(genErr)
 
 	//
diff --git a/examples/listen/main.go b/examples/listen/main.go
index 36940f7..436b52b 100644
--- a/examples/listen/main.go
+++ b/examples/listen/main.go
@@ -8,6 +8,7 @@ import (
 
 	"github.com/pion/dtls/v2"
 	"github.com/pion/dtls/v2/examples/util"
+	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
 )
 
 func main() {
@@ -15,7 +16,7 @@ func main() {
 	addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444}
 
 	// Generate a certificate and private key to secure the connection
-	certificate, genErr := dtls.GenerateSelfSigned()
+	certificate, genErr := selfsign.GenerateSelfSigned()
 	util.Check(genErr)
 
 	//
diff --git a/closer.go b/internal/closer/closer.go
similarity index 82%
rename from closer.go
rename to internal/closer/closer.go
index 8af9278..b99e13e 100644
--- a/closer.go
+++ b/internal/closer/closer.go
@@ -1,4 +1,5 @@
-package dtls
+// Package closer provides signaling channel for shutdown
+package closer
 
 import (
 	"context"
@@ -33,6 +34,11 @@ func (c *Closer) Done() <-chan struct{} {
 	return c.ctx.Done()
 }
 
+// Err returns an error of the context
+func (c *Closer) Err() error {
+	return c.ctx.Err()
+}
+
 // Close sends a signal to trigger the ctx done channel
 func (c *Closer) Close() {
 	c.closeFunc()
diff --git a/internal/crypto/ccm/ccm.go b/pkg/crypto/ccm/ccm.go
similarity index 100%
rename from internal/crypto/ccm/ccm.go
rename to pkg/crypto/ccm/ccm.go
diff --git a/internal/crypto/ccm/ccm_test.go b/pkg/crypto/ccm/ccm_test.go
similarity index 100%
rename from internal/crypto/ccm/ccm_test.go
rename to pkg/crypto/ccm/ccm_test.go
diff --git a/pkg/crypto/selfsign/selfsign.go b/pkg/crypto/selfsign/selfsign.go
new file mode 100644
index 0000000..0ccbe43
--- /dev/null
+++ b/pkg/crypto/selfsign/selfsign.go
@@ -0,0 +1,81 @@
+// Package selfsign is a test helper that generates self signed certificate.
+package selfsign
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/hex"
+	"errors"
+	"math/big"
+	"time"
+
+	"golang.org/x/crypto/ed25519"
+)
+
+var errInvalidPrivateKey = errors.New("selfsign: invalid private key type")
+
+// GenerateSelfSigned creates a self-signed certificate
+func GenerateSelfSigned() (tls.Certificate, error) {
+	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		return tls.Certificate{}, err
+	}
+
+	return SelfSign(priv)
+}
+
+// SelfSign creates a self-signed certificate from a elliptic curve key
+func SelfSign(key crypto.PrivateKey) (tls.Certificate, error) {
+	var (
+		pubKey    crypto.PublicKey
+		origin    = make([]byte, 16)
+		maxBigInt = new(big.Int) // Max random value, a 130-bits integer, i.e 2^130 - 1
+	)
+
+	switch k := key.(type) {
+	case ed25519.PrivateKey:
+		pubKey = k.Public()
+	case *ecdsa.PrivateKey:
+		pubKey = k.Public()
+	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
+	}
+
+	template := x509.Certificate{
+		ExtKeyUsage: []x509.ExtKeyUsage{
+			x509.ExtKeyUsageClientAuth,
+			x509.ExtKeyUsageServerAuth,
+		},
+		BasicConstraintsValid: true,
+		NotBefore:             time.Now(),
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+		NotAfter:              time.Now().AddDate(0, 1, 0),
+		SerialNumber:          serialNumber,
+		Version:               2,
+		Subject:               pkix.Name{CommonName: hex.EncodeToString(origin)},
+		IsCA:                  true,
+	}
+
+	raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey, key)
+	if err != nil {
+		return tls.Certificate{}, err
+	}
+
+	return tls.Certificate{
+		Certificate: [][]byte{raw},
+		PrivateKey:  key,
+	}, nil
+}
diff --git a/util.go b/util.go
index 14efd6f..09de441 100644
--- a/util.go
+++ b/util.go
@@ -1,19 +1,7 @@
 package dtls
 
 import (
-	"crypto"
-	"crypto/ecdsa"
-	"crypto/elliptic"
-	"crypto/rand"
-	"crypto/tls"
-	"crypto/x509"
-	"crypto/x509/pkix"
 	"encoding/binary"
-	"encoding/hex"
-	"math/big"
-	"time"
-
-	"golang.org/x/crypto/ed25519"
 )
 
 // Parse a big endian uint24
@@ -39,67 +27,6 @@ func putBigEndianUint48(out []byte, in uint64) {
 	copy(out, tmp[2:])
 }
 
-// GenerateSelfSigned creates a self-signed certificate
-func GenerateSelfSigned() (tls.Certificate, error) {
-	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-	if err != nil {
-		return tls.Certificate{}, err
-	}
-
-	return SelfSign(priv)
-}
-
-// SelfSign creates a self-signed certificate from a elliptic curve key
-func SelfSign(key crypto.PrivateKey) (tls.Certificate, error) {
-	var (
-		pubKey    crypto.PublicKey
-		origin    = make([]byte, 16)
-		maxBigInt = new(big.Int) // Max random value, a 130-bits integer, i.e 2^130 - 1
-	)
-
-	switch k := key.(type) {
-	case ed25519.PrivateKey:
-		pubKey = k.Public()
-	case *ecdsa.PrivateKey:
-		pubKey = k.Public()
-	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
-	}
-
-	template := x509.Certificate{
-		ExtKeyUsage: []x509.ExtKeyUsage{
-			x509.ExtKeyUsageClientAuth,
-			x509.ExtKeyUsageServerAuth,
-		},
-		BasicConstraintsValid: true,
-		NotBefore:             time.Now(),
-		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
-		NotAfter:              time.Now().AddDate(0, 1, 0),
-		SerialNumber:          serialNumber,
-		Version:               2,
-		Subject:               pkix.Name{CommonName: hex.EncodeToString(origin)},
-		IsCA:                  true,
-	}
-
-	raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey, key)
-	if err != nil {
-		return tls.Certificate{}, err
-	}
-
-	return tls.Certificate{
-		Certificate: [][]byte{raw},
-		PrivateKey:  key,
-	}, nil
-}
-
 func max(a, b int) int {
 	if a > b {
 		return a


Test patch:
diff --git a/bench_test.go b/bench_test.go
index cab9c1c..a2e8a25 100644
--- a/bench_test.go
+++ b/bench_test.go
@@ -7,6 +7,7 @@ import (
 	"testing"
 	"time"
 
+	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
 	"github.com/pion/logging"
 	"github.com/pion/transport/test"
 )
@@ -16,7 +17,7 @@ func TestSimpleReadWrite(t *testing.T) {
 	defer report()
 
 	ca, cb := net.Pipe()
-	certificate, err := GenerateSelfSigned()
+	certificate, err := selfsign.GenerateSelfSigned()
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -65,7 +66,7 @@ func TestSimpleReadWrite(t *testing.T) {
 func benchmarkConn(b *testing.B, n int64) {
 	b.Run(fmt.Sprintf("%d", n), func(b *testing.B) {
 		ca, cb := net.Pipe()
-		certificate, err := GenerateSelfSigned()
+		certificate, err := selfsign.GenerateSelfSigned()
 		server := make(chan *Conn)
 		go func() {
 			s, sErr := testServer(cb, &Config{
diff --git a/config_test.go b/config_test.go
index c938d5e..13e4ac3 100644
--- a/config_test.go
+++ b/config_test.go
@@ -5,6 +5,8 @@ import (
 	"crypto/x509"
 	"encoding/pem"
 	"testing"
+
+	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
 )
 
 func TestValidateConfig(t *testing.T) {
@@ -14,7 +16,7 @@ func TestValidateConfig(t *testing.T) {
 	}
 
 	//PSK and Certificate
-	cert, err := GenerateSelfSigned()
+	cert, err := selfsign.GenerateSelfSigned()
 	if err != nil {
 		t.Fatalf("TestValidateConfig: Config validation error(%v), self signed certificate not generated", err)
 		return
diff --git a/conn_test.go b/conn_test.go
index 91eb7a6..1dbafb3 100644
--- a/conn_test.go
+++ b/conn_test.go
@@ -12,6 +12,7 @@ import (
 	"time"
 
 	"github.com/pion/dtls/v2/internal/dpipe"
+	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
 	"github.com/pion/transport/test"
 )
 
@@ -135,7 +136,7 @@ func pipeMemory() (*Conn, *Conn, error) {
 
 func testClient(c net.Conn, cfg *Config, generateCertificate bool) (*Conn, error) {
 	if generateCertificate {
-		clientCert, err := GenerateSelfSigned()
+		clientCert, err := selfsign.GenerateSelfSigned()
 		if err != nil {
 			return nil, err
 		}
@@ -147,7 +148,7 @@ func testClient(c net.Conn, cfg *Config, generateCertificate bool) (*Conn, error
 
 func testServer(c net.Conn, cfg *Config, generateCertificate bool) (*Conn, error) {
 	if generateCertificate {
-		serverCert, err := GenerateSelfSigned()
+		serverCert, err := selfsign.GenerateSelfSigned()
 		if err != nil {
 			return nil, err
 		}
@@ -443,7 +444,7 @@ func TestSRTPConfiguration(t *testing.T) {
 }
 
 func TestClientCertificate(t *testing.T) {
-	srvCert, err := GenerateSelfSigned()
+	srvCert, err := selfsign.GenerateSelfSigned()
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -454,7 +455,7 @@ func TestClientCertificate(t *testing.T) {
 	}
 	srvCAPool.AddCert(srvCertificate)
 
-	cert, err := GenerateSelfSigned()
+	cert, err := selfsign.GenerateSelfSigned()
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -744,7 +745,7 @@ func TestExtendedMasterSecret(t *testing.T) {
 func TestServerCertificate(t *testing.T) {
 	t.Parallel()
 
-	cert, err := GenerateSelfSigned()
+	cert, err := selfsign.GenerateSelfSigned()
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/e2e/e2e_lossy_test.go b/e2e/e2e_lossy_test.go
index d7ec300..5d537d2 100644
--- a/e2e/e2e_lossy_test.go
+++ b/e2e/e2e_lossy_test.go
@@ -8,6 +8,7 @@ import (
 	"time"
 
 	"github.com/pion/dtls/v2"
+	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
 	transportTest "github.com/pion/transport/test"
 )
 
@@ -25,12 +26,12 @@ func TestPionE2ELossy(t *testing.T) {
 		err      error
 	}
 
-	serverCert, err := dtls.GenerateSelfSigned()
+	serverCert, err := selfsign.GenerateSelfSigned()
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	clientCert, err := dtls.GenerateSelfSigned()
+	clientCert, err := selfsign.GenerateSelfSigned()
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go
index dd9224e..073a1a4 100644
--- a/e2e/e2e_test.go
+++ b/e2e/e2e_test.go
@@ -13,6 +13,7 @@ import (
 	"time"
 
 	"github.com/pion/dtls/v2"
+	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
 	"github.com/pion/transport/test"
 )
 
@@ -195,7 +196,7 @@ func TestPionE2ESimple(t *testing.T) {
 		dtls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
 		dtls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
 	} {
-		cert, err := dtls.GenerateSelfSigned()
+		cert, err := selfsign.GenerateSelfSigned()
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -250,7 +251,7 @@ func TestPionE2EMTUs(t *testing.T) {
 		1000,
 		100,
 	} {
-		cert, err := dtls.GenerateSelfSigned()
+		cert, err := selfsign.GenerateSelfSigned()
 		if err != nil {
 			t.Fatal(err)
 		}
diff --git a/e2e/e2e_v113_test.go b/e2e/e2e_v113_test.go
index eab820a..6f34d0d 100644
--- a/e2e/e2e_v113_test.go
+++ b/e2e/e2e_v113_test.go
@@ -11,6 +11,7 @@ import (
 	"golang.org/x/crypto/ed25519"
 
 	"github.com/pion/dtls/v2"
+	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
 	"github.com/pion/transport/test"
 )
 
@@ -36,7 +37,7 @@ func TestPionE2ESimpleED25519(t *testing.T) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		cert, err := dtls.SelfSign(key)
+		cert, err := selfsign.SelfSign(key)
 		if err != nil {
 			t.Fatal(err)
 		}
diff --git a/resume_test.go b/resume_test.go
index e7cb905..c17004a 100644
--- a/resume_test.go
+++ b/resume_test.go
@@ -8,6 +8,8 @@ import (
 	"sync"
 	"testing"
 	"time"
+
+	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
 )
 
 func TestResumeClient(t *testing.T) {
@@ -24,7 +26,7 @@ func fatal(t *testing.T, errChan chan error, err error) {
 }
 
 func DoTestResume(t *testing.T, newLocal, newRemote func(net.Conn, *Config) (*Conn, error)) {
-	certificate, err := GenerateSelfSigned()
+	certificate, err := selfsign.GenerateSelfSigned()
 	if err != nil {
 		t.Fatal(err)
 	}