mirror of
				https://github.com/bjdgyc/anylink.git
				synced 2025-11-04 11:06:22 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			120 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package handshake
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/binary"
 | 
						|
 | 
						|
	"github.com/pion/dtls/v2/pkg/crypto/elliptic"
 | 
						|
	"github.com/pion/dtls/v2/pkg/crypto/hash"
 | 
						|
	"github.com/pion/dtls/v2/pkg/crypto/signature"
 | 
						|
)
 | 
						|
 | 
						|
// MessageServerKeyExchange supports ECDH and PSK
 | 
						|
type MessageServerKeyExchange struct {
 | 
						|
	IdentityHint []byte
 | 
						|
 | 
						|
	EllipticCurveType  elliptic.CurveType
 | 
						|
	NamedCurve         elliptic.Curve
 | 
						|
	PublicKey          []byte
 | 
						|
	HashAlgorithm      hash.Algorithm
 | 
						|
	SignatureAlgorithm signature.Algorithm
 | 
						|
	Signature          []byte
 | 
						|
}
 | 
						|
 | 
						|
// Type returns the Handshake Type
 | 
						|
func (m MessageServerKeyExchange) Type() Type {
 | 
						|
	return TypeServerKeyExchange
 | 
						|
}
 | 
						|
 | 
						|
// Marshal encodes the Handshake
 | 
						|
func (m *MessageServerKeyExchange) Marshal() ([]byte, error) {
 | 
						|
	if m.IdentityHint != nil {
 | 
						|
		out := append([]byte{0x00, 0x00}, m.IdentityHint...)
 | 
						|
		binary.BigEndian.PutUint16(out, uint16(len(out)-2))
 | 
						|
		return out, nil
 | 
						|
	}
 | 
						|
 | 
						|
	out := []byte{byte(m.EllipticCurveType), 0x00, 0x00}
 | 
						|
	binary.BigEndian.PutUint16(out[1:], uint16(m.NamedCurve))
 | 
						|
 | 
						|
	out = append(out, byte(len(m.PublicKey)))
 | 
						|
	out = append(out, m.PublicKey...)
 | 
						|
 | 
						|
	if m.HashAlgorithm == hash.None && m.SignatureAlgorithm == signature.Anonymous && len(m.Signature) == 0 {
 | 
						|
		return out, nil
 | 
						|
	}
 | 
						|
 | 
						|
	out = append(out, []byte{byte(m.HashAlgorithm), byte(m.SignatureAlgorithm), 0x00, 0x00}...)
 | 
						|
	binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.Signature)))
 | 
						|
	out = append(out, m.Signature...)
 | 
						|
 | 
						|
	return out, nil
 | 
						|
}
 | 
						|
 | 
						|
// Unmarshal populates the message from encoded data
 | 
						|
func (m *MessageServerKeyExchange) Unmarshal(data []byte) error {
 | 
						|
	if len(data) < 2 {
 | 
						|
		return errBufferTooSmall
 | 
						|
	}
 | 
						|
 | 
						|
	// If parsed as PSK return early and only populate PSK Identity Hint
 | 
						|
	if pskLength := binary.BigEndian.Uint16(data); len(data) == int(pskLength+2) {
 | 
						|
		m.IdentityHint = append([]byte{}, data[2:]...)
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
 | 
						|
	if _, ok := elliptic.CurveTypes()[elliptic.CurveType(data[0])]; ok {
 | 
						|
		m.EllipticCurveType = elliptic.CurveType(data[0])
 | 
						|
	} else {
 | 
						|
		return errInvalidEllipticCurveType
 | 
						|
	}
 | 
						|
 | 
						|
	if len(data[1:]) < 2 {
 | 
						|
		return errBufferTooSmall
 | 
						|
	}
 | 
						|
	m.NamedCurve = elliptic.Curve(binary.BigEndian.Uint16(data[1:3]))
 | 
						|
	if _, ok := elliptic.Curves()[m.NamedCurve]; !ok {
 | 
						|
		return errInvalidNamedCurve
 | 
						|
	}
 | 
						|
	if len(data) < 4 {
 | 
						|
		return errBufferTooSmall
 | 
						|
	}
 | 
						|
 | 
						|
	publicKeyLength := int(data[3])
 | 
						|
	offset := 4 + publicKeyLength
 | 
						|
	if len(data) < offset {
 | 
						|
		return errBufferTooSmall
 | 
						|
	}
 | 
						|
	m.PublicKey = append([]byte{}, data[4:offset]...)
 | 
						|
 | 
						|
	// Anon connection doesn't contains hashAlgorithm, signatureAlgorithm, signature
 | 
						|
	if len(data) == offset {
 | 
						|
		return nil
 | 
						|
	} else if len(data) <= offset {
 | 
						|
		return errBufferTooSmall
 | 
						|
	}
 | 
						|
 | 
						|
	m.HashAlgorithm = hash.Algorithm(data[offset])
 | 
						|
	if _, ok := hash.Algorithms()[m.HashAlgorithm]; !ok {
 | 
						|
		return errInvalidHashAlgorithm
 | 
						|
	}
 | 
						|
	offset++
 | 
						|
	if len(data) <= offset {
 | 
						|
		return errBufferTooSmall
 | 
						|
	}
 | 
						|
	m.SignatureAlgorithm = signature.Algorithm(data[offset])
 | 
						|
	if _, ok := signature.Algorithms()[m.SignatureAlgorithm]; !ok {
 | 
						|
		return errInvalidSignatureAlgorithm
 | 
						|
	}
 | 
						|
	offset++
 | 
						|
	if len(data) < offset+2 {
 | 
						|
		return errBufferTooSmall
 | 
						|
	}
 | 
						|
	signatureLength := int(binary.BigEndian.Uint16(data[offset:]))
 | 
						|
	offset += 2
 | 
						|
	if len(data) < offset+signatureLength {
 | 
						|
		return errBufferTooSmall
 | 
						|
	}
 | 
						|
	m.Signature = append([]byte{}, data[offset:offset+signatureLength]...)
 | 
						|
	return nil
 | 
						|
}
 |