package dns
import (
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"encoding/binary"
"math/big"
"time"
)
func (rr *SIG ) Sign (k crypto .Signer , m *Msg ) ([]byte , error ) {
if k == nil {
return nil , ErrPrivKey
}
if rr .KeyTag == 0 || rr .SignerName == "" || rr .Algorithm == 0 {
return nil , ErrKey
}
rr .Hdr = RR_Header {Name : "." , Rrtype : TypeSIG , Class : ClassANY , Ttl : 0 }
rr .OrigTtl , rr .TypeCovered , rr .Labels = 0 , 0 , 0
buf := make ([]byte , m .Len ()+Len (rr ))
mbuf , err := m .PackBuffer (buf )
if err != nil {
return nil , err
}
if &buf [0 ] != &mbuf [0 ] {
return nil , ErrBuf
}
off , err := PackRR (rr , buf , len (mbuf ), nil , false )
if err != nil {
return nil , err
}
buf = buf [:off :cap (buf )]
h , cryptohash , err := hashFromAlgorithm (rr .Algorithm )
if err != nil {
return nil , err
}
h .Write (buf [len (mbuf )+1 +2 +2 +4 +2 :])
h .Write (buf [:len (mbuf )])
signature , err := sign (k , h .Sum (nil ), cryptohash , rr .Algorithm )
if err != nil {
return nil , err
}
rr .Signature = toBase64 (signature )
buf = append (buf , signature ...)
if len (buf ) > int (^uint16 (0 )) {
return nil , ErrBuf
}
rdoff := len (mbuf ) + 1 + 2 + 2 + 4
rdlen := binary .BigEndian .Uint16 (buf [rdoff :])
rdlen += uint16 (len (signature ))
binary .BigEndian .PutUint16 (buf [rdoff :], rdlen )
adc := binary .BigEndian .Uint16 (buf [10 :])
adc ++
binary .BigEndian .PutUint16 (buf [10 :], adc )
return buf , nil
}
func (rr *SIG ) Verify (k *KEY , buf []byte ) error {
if k == nil {
return ErrKey
}
if rr .KeyTag == 0 || rr .SignerName == "" || rr .Algorithm == 0 {
return ErrKey
}
h , cryptohash , err := hashFromAlgorithm (rr .Algorithm )
if err != nil {
return err
}
buflen := len (buf )
qdc := binary .BigEndian .Uint16 (buf [4 :])
anc := binary .BigEndian .Uint16 (buf [6 :])
auc := binary .BigEndian .Uint16 (buf [8 :])
adc := binary .BigEndian .Uint16 (buf [10 :])
offset := headerSize
for i := uint16 (0 ); i < qdc && offset < buflen ; i ++ {
_, offset , err = UnpackDomainName (buf , offset )
if err != nil {
return err
}
offset += 2 + 2
}
for i := uint16 (1 ); i < anc +auc +adc && offset < buflen ; i ++ {
_, offset , err = UnpackDomainName (buf , offset )
if err != nil {
return err
}
offset += 2 + 2 + 4
if offset +1 >= buflen {
continue
}
rdlen := binary .BigEndian .Uint16 (buf [offset :])
offset += 2
offset += int (rdlen )
}
if offset >= buflen {
return &Error {err : "overflowing unpacking signed message" }
}
bodyend := offset
_, offset , err = UnpackDomainName (buf , offset )
if err != nil {
return err
}
offset += 2 + 2 + 4 + 2
sigstart := offset
offset += 2 + 1 + 1 + 4
if offset +4 +4 >= buflen {
return &Error {err : "overflow unpacking signed message" }
}
expire := binary .BigEndian .Uint32 (buf [offset :])
offset += 4
incept := binary .BigEndian .Uint32 (buf [offset :])
offset += 4
now := uint32 (time .Now ().Unix ())
if now < incept || now > expire {
return ErrTime
}
offset += 2
var signername string
signername , offset , err = UnpackDomainName (buf , offset )
if err != nil {
return err
}
if !equal (signername , k .Header ().Name ) {
return &Error {err : "signer name doesn't match key name" }
}
sigend := offset
h .Write (buf [sigstart :sigend ])
h .Write (buf [:10 ])
h .Write ([]byte {
byte ((adc - 1 ) << 8 ),
byte (adc - 1 ),
})
h .Write (buf [12 :bodyend ])
hashed := h .Sum (nil )
sig := buf [sigend :]
switch k .Algorithm {
case RSASHA1 , RSASHA256 , RSASHA512 :
pk := k .publicKeyRSA ()
if pk != nil {
return rsa .VerifyPKCS1v15 (pk , cryptohash , hashed , sig )
}
case ECDSAP256SHA256 , ECDSAP384SHA384 :
pk := k .publicKeyECDSA ()
r := new (big .Int ).SetBytes (sig [:len (sig )/2 ])
s := new (big .Int ).SetBytes (sig [len (sig )/2 :])
if pk != nil {
if ecdsa .Verify (pk , hashed , r , s ) {
return nil
}
return ErrSig
}
case ED25519 :
pk := k .publicKeyED25519 ()
if pk != nil {
if ed25519 .Verify (pk , hashed , sig ) {
return nil
}
return ErrSig
}
}
return ErrKeyAlg
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .