Skip to content

Instantly share code, notes, and snippets.

@Sean-Der
Last active January 28, 2021 06:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sean-Der/1e4192b37c8a9ef5cf18d6272d22e503 to your computer and use it in GitHub Desktop.
Save Sean-Der/1e4192b37c8a9ef5cf18d6272d22e503 to your computer and use it in GitHub Desktop.
Pion DTLS AECDH-AES128-SHA Example
  • openssl s_server -dtls -cipher "AECDH-AES128-SHA:@SECLEVEL=0" -state -accept 127.0.0.1:4444 -nocert -msg
  • openssl s_client -dtls -cipher "AECDH-AES128-SHA:@SECLEVEL=0" -state -connect 127.0.0.1:4444
package main
import (
"context"
"net"
"time"
"github.com/pion/dtls/v2"
)
func dial() {
// Prepare the IP to connect to
addr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 4444}
// Connect to a DTLS server
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
_, err := dtls.DialWithContext(ctx, "udp", addr, &dtls.Config{
CustomCipherSuites: func() []dtls.CipherSuite { return []dtls.CipherSuite{&TLSAecdhAes128Sha{}} },
CipherSuites: []dtls.CipherSuiteID{},
})
if err != nil {
panic(err)
}
}
package main
import (
"net"
"github.com/pion/dtls/v2"
)
func listener() {
// Prepare the IP to listen on
addr := &net.UDPAddr{IP: net.ParseIP("0.0.0.0"), Port: 4444}
// Prepare the configuration of the DTLS connection
config := &dtls.Config{
CustomCipherSuites: func() []dtls.CipherSuite { return []dtls.CipherSuite{&TLSAecdhAes128Sha{}} },
CipherSuites: []dtls.CipherSuiteID{},
}
// Connect to a DTLS server
listener, err := dtls.Listen("udp", addr, config)
if err != nil {
panic(err)
}
_, err = listener.Accept()
if err != nil {
panic(err)
}
}
package main
import (
"crypto/sha1"
"crypto/sha256"
"fmt"
"hash"
"sync/atomic"
"github.com/pion/dtls/v2"
"github.com/pion/dtls/v2/pkg/crypto/ciphersuite"
"github.com/pion/dtls/v2/pkg/crypto/clientcertificate"
"github.com/pion/dtls/v2/pkg/crypto/prf"
"github.com/pion/dtls/v2/pkg/protocol/recordlayer"
)
func main() {
dial()
if false {
listener()
}
}
// TLSAecdhAes128Sha implements the TLS_ADH_AES128_SHA CipherSuite
type TLSAecdhAes128Sha struct {
cbc atomic.Value // *cryptoCBC
}
// CertificateType returns what type of certificate this CipherSuite exchanges
func (c *TLSAecdhAes128Sha) CertificateType() clientcertificate.Type {
return clientcertificate.Type(0)
}
// ID returns the ID of the CipherSuite
func (c *TLSAecdhAes128Sha) ID() dtls.CipherSuiteID {
return 0xC018
}
func (c *TLSAecdhAes128Sha) String() string {
return "AECDH-AES128-SHA"
}
// HashFunc returns the hashing func for this CipherSuite
func (c *TLSAecdhAes128Sha) HashFunc() func() hash.Hash {
return sha256.New
}
// AuthenticationType controls what authentication method is using during the handshake
func (c *TLSAecdhAes128Sha) AuthenticationType() dtls.CipherSuiteAuthenticationType {
return dtls.CipherSuiteAuthenticationTypeAnonymous
}
// IsInitialized returns if the CipherSuite has keying material and can
// encrypt/decrypt packets
func (c *TLSAecdhAes128Sha) IsInitialized() bool {
return c.cbc.Load() != nil
}
// Init initializes the internal Cipher with keying material
func (c *TLSAecdhAes128Sha) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error {
const (
prfMacLen = 20
prfKeyLen = 16
prfIvLen = 16
)
keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc())
if err != nil {
return err
}
var cbc *ciphersuite.CBC
if isClient {
cbc, err = ciphersuite.NewCBC(
keys.ClientWriteKey, keys.ClientWriteIV, keys.ClientMACKey,
keys.ServerWriteKey, keys.ServerWriteIV, keys.ServerMACKey,
sha1.New,
)
} else {
cbc, err = ciphersuite.NewCBC(
keys.ServerWriteKey, keys.ServerWriteIV, keys.ServerMACKey,
keys.ClientWriteKey, keys.ClientWriteIV, keys.ClientMACKey,
sha1.New,
)
}
c.cbc.Store(cbc)
return err
}
// Encrypt encrypts a single TLS RecordLayer
func (c *TLSAecdhAes128Sha) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) {
cbc := c.cbc.Load()
if cbc == nil {
return nil, fmt.Errorf("CipherSuite is not ready, unable to encrypt")
}
return cbc.(*ciphersuite.CBC).Encrypt(pkt, raw)
}
// Decrypt decrypts a single TLS RecordLayer
func (c *TLSAecdhAes128Sha) Decrypt(raw []byte) ([]byte, error) {
cbc := c.cbc.Load()
if cbc == nil { // !c.isInitialized()
return nil, fmt.Errorf("CipherSuite is not ready, unable to decrypt")
}
return cbc.(*ciphersuite.CBC).Decrypt(raw)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment