예제 #1
0
파일: main.go 프로젝트: tcnksm/go-crypto
func main() {
	var privateKey dsa.PrivateKey
	params := &privateKey.Parameters

	// L2048N224 is length of L and N
	if err := dsa.GenerateParameters(params, rand.Reader, dsa.L2048N224); err != nil {
		fmt.Printf("Err: %s", err)
		return
	}

	if err := dsa.GenerateKey(&privateKey, rand.Reader); err != nil {
		fmt.Printf("Err: %s", err)
		return
	}

	hashed := []byte("This is test hashed message")

	// It returns the signature as a pair of integers.
	r, s, err := dsa.Sign(rand.Reader, &privateKey, hashed)
	if err != nil {
		fmt.Printf("Err: %s", err)
		return
	}

	// Check signnature can be verified
	publicKey := &privateKey.PublicKey
	if dsa.Verify(publicKey, hashed, r, s) {
		fmt.Printf("Verified\n")
	}
}
예제 #2
0
func SignatureSign(hash []byte, priv *dsa.PrivateKey) (r, s []byte, err error) {
	ri, si, err := dsa.Sign(rand.Reader, priv, hash)
	if err != nil {
		return nil, nil, err
	}
	return []byte(base64.StdEncoding.EncodeToString(ri.Bytes())), []byte(base64.StdEncoding.EncodeToString(si.Bytes())), nil
}
예제 #3
0
파일: signature.go 프로젝트: WXB506/golang
// Sign signs a message with a private key. The hash, h, must contain
// the hash of the message to be signed and will be mutated by this function.
// On success, the signature is stored in sig. Call Serialize to write it out.
func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err os.Error) {
	sig.outSubpackets = sig.buildSubpackets()
	digest, err := sig.signPrepareHash(h)
	if err != nil {
		return
	}

	switch priv.PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
		sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand.Reader, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
		sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
	case PubKeyAlgoDSA:
		r, s, err := dsa.Sign(rand.Reader, priv.PrivateKey.(*dsa.PrivateKey), digest)
		if err == nil {
			sig.DSASigR.bytes = r.Bytes()
			sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
			sig.DSASigS.bytes = s.Bytes()
			sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
		}
	default:
		err = error.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
	}

	return
}
예제 #4
0
// Sign signs a message with a private key. The hash, h, must contain
// the hash of the message to be signed and will be mutated by this function.
// On success, the signature is stored in sig. Call Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
	sig.outSubpackets = sig.buildSubpackets()
	digest, err := sig.signPrepareHash(h)
	if err != nil {
		return
	}

	switch priv.PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
		sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
		sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
	case PubKeyAlgoDSA:
		dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)

		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
		subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
		if len(digest) > subgroupSize {
			digest = digest[:subgroupSize]
		}
		r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
		if err == nil {
			sig.DSASigR.bytes = r.Bytes()
			sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
			sig.DSASigS.bytes = s.Bytes()
			sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
		}
	default:
		err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
	}

	return
}
예제 #5
0
파일: signature.go 프로젝트: radhermit/gcc
// SignDSA signs a message with a DSA private key. The hash, h, must contain
// the hash of the message to be signed and will be mutated by this function.
// On success, the signature is stored in sig. Call Serialize to write it out.
func (sig *Signature) SignDSA(h hash.Hash, priv *dsa.PrivateKey) (err os.Error) {
	digest, err := sig.signPrepareHash(h)
	if err != nil {
		return
	}
	sig.DSASigR, sig.DSASigS, err = dsa.Sign(rand.Reader, priv, digest)
	return
}
예제 #6
0
func Sign() {
	key := Key()
	hash := HashMessage()
	r, s, err := dsa.Sign(rand.Reader, key, hash)
	if err != nil {
		log.Fatalf("failed to sign message: %s", err)
	}
	log.Printf("r: %v", r)
	log.Printf("s: %v", s)
}
예제 #7
0
func (p *DSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) {
	r1, s1, err := dsa.Sign(rand.Reader, (*dsa.PrivateKey)(p), hashed)
	if err != nil {
		return nil, err
	}
	t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
	signature := []byte{byte(t)}
	signature = append(signature, intToBytes(r1, 20)...)
	signature = append(signature, intToBytes(s1, 20)...)
	return signature, nil
}
예제 #8
0
파일: keys.go 프로젝트: juniorz/otr3
// Sign will generate a signature of a hashed data using dsa Sign.
func (priv *PrivateKey) Sign(rand io.Reader, hashed []byte) ([]byte, error) {
	r, s, err := dsa.Sign(rand, &priv.PrivateKey, hashed)
	if err == nil {
		rBytes := r.Bytes()
		sBytes := s.Bytes()

		out := make([]byte, 40)
		copy(out[20-len(rBytes):], rBytes)
		copy(out[len(out)-len(sBytes):], sBytes)
		return out, nil
	}
	return nil, err
}
예제 #9
0
파일: signature.go 프로젝트: naunga/vault
// Sign signs a message with a private key. The hash, h, must contain
// the hash of the message to be signed and will be mutated by this function.
// On success, the signature is stored in sig. Call Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
	signer, hashIsSigner := h.(Signer)

	if !hashIsSigner && (priv == nil || priv.PrivateKey == nil) {
		err = errors.InvalidArgumentError("attempting to sign with nil PrivateKey")
		return
	}

	sig.outSubpackets = sig.buildSubpackets()
	digest, err := sig.signPrepareHash(h)
	if err != nil {
		return
	}

	if hashIsSigner {
		err = signer.Sign(sig)
		return
	}

	switch priv.PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
		sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
		sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
	case PubKeyAlgoDSA:
		dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)

		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
		subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
		if len(digest) > subgroupSize {
			digest = digest[:subgroupSize]
		}
		r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
		if err == nil {
			sig.DSASigR.bytes = r.Bytes()
			sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
			sig.DSASigS.bytes = s.Bytes()
			sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
		}
	case PubKeyAlgoECDSA:
		r, s, err := ecdsa.Sign(config.Random(), priv.PrivateKey.(*ecdsa.PrivateKey), digest)
		if err == nil {
			sig.ECDSASigR = FromBig(r)
			sig.ECDSASigS = FromBig(s)
		}
	default:
		err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
	}

	return
}
예제 #10
0
파일: keys.go 프로젝트: kshi0310/geard
func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) ([]byte, error) {
	h := crypto.SHA1.New()
	h.Write(data)
	digest := h.Sum(nil)
	r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
	if err != nil {
		return nil, err
	}

	sig := make([]byte, 40)
	copy(sig[:20], r.Bytes())
	copy(sig[20:], s.Bytes())
	return sig, nil
}
예제 #11
0
파일: dsa.go 프로젝트: majestrate/go-i2p
func (ds *DSASigner) SignHash(h []byte) (sig []byte, err error) {
	var r, s *big.Int
	r, s, err = dsa.Sign(rand.Reader, ds.k, h)
	if err == nil {
		sig = make([]byte, 40)
		rb := r.Bytes()
		rl := len(rb)
		copy(sig[20-rl:20], rb)
		sb := s.Bytes()
		sl := len(sb)
		copy(sig[20+(20-sl):], sb)
	}
	return
}
예제 #12
0
func (dk *dsaKey) Sign(msg []byte) ([]byte, error) {
	h := sha1.New()
	h.Write(msg)
	r, s, err := dsa.Sign(rand.Reader, &dk.key, h.Sum(nil))
	if err != nil {
		return nil, err
	}
	sig := dsaSignature{r, s}
	b, err := asn1.Marshal(sig)
	if err != nil {
		return nil, err
	}
	return b, nil
}
예제 #13
0
파일: signature.go 프로젝트: 40a/ejson
// Sign signs a message with a private key. The hash, h, must contain
// the hash of the message to be signed and will be mutated by this function.
// On success, the signature is stored in sig. Call Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
	sig.outSubpackets = sig.buildSubpackets()
	digest, err := sig.signPrepareHash(h)
	if err != nil {
		return
	}

	switch priv.PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
		// supports both *rsa.PrivateKey and crypto.Signer
		sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
		sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
	case PubKeyAlgoDSA:
		dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)

		// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
		subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
		if len(digest) > subgroupSize {
			digest = digest[:subgroupSize]
		}
		r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
		if err == nil {
			sig.DSASigR.bytes = r.Bytes()
			sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
			sig.DSASigS.bytes = s.Bytes()
			sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
		}
	case PubKeyAlgoECDSA:
		var r, s *big.Int
		if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
			// direct support, avoid asn1 wrapping/unwrapping
			r, s, err = ecdsa.Sign(config.Random(), pk, digest)
		} else {
			var b []byte
			b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, nil)
			if err == nil {
				r, s, err = unwrapECDSASig(b)
			}
		}
		if err == nil {
			sig.ECDSASigR = fromBig(r)
			sig.ECDSASigS = fromBig(s)
		}
	default:
		err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
	}

	return
}
예제 #14
0
파일: otr.go 프로젝트: sneha29shukla/mig
func (priv *PrivateKey) Sign(rand io.Reader, hashed []byte) []byte {
	r, s, err := dsa.Sign(rand, &priv.PrivateKey, hashed)
	if err != nil {
		panic(err.Error())
	}
	rBytes := r.Bytes()
	sBytes := s.Bytes()
	if len(rBytes) > dsaSubgroupBytes || len(sBytes) > dsaSubgroupBytes {
		panic("DSA signature too large")
	}

	out := make([]byte, 2*dsaSubgroupBytes)
	copy(out[dsaSubgroupBytes-len(rBytes):], rBytes)
	copy(out[len(out)-len(sBytes):], sBytes)
	return out
}
예제 #15
0
// Sign signs a message with a private key. The hash, h, must contain
// the hash of the message to be signed and will be mutated by this function.
// On success, the signature is stored in sig. Call Serialize to write it out.
func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err os.Error) {
	digest, err := sig.signPrepareHash(h)
	if err != nil {
		return
	}

	switch priv.PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
		sig.RSASignature, err = rsa.SignPKCS1v15(rand.Reader, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
	case PubKeyAlgoDSA:
		sig.DSASigR, sig.DSASigS, err = dsa.Sign(rand.Reader, priv.PrivateKey.(*dsa.PrivateKey), digest)
	default:
		err = error.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
	}

	return
}
예제 #16
0
파일: keys.go 프로젝트: backkom/leanote-all
func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
	h := crypto.SHA1.New()
	h.Write(data)
	digest := h.Sum(nil)
	r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
	if err != nil {
		return nil, err
	}

	sig := make([]byte, 40)
	rb := r.Bytes()
	sb := s.Bytes()

	copy(sig[20-len(rb):20], rb)
	copy(sig[40-len(sb):], sb)

	return &Signature{
		Format: k.PublicKey().Type(),
		Blob:   sig,
	}, nil
}
예제 #17
0
// copied from crypto/openpgp/packet.(*Signature).Sign()
func MakeSignature(pgpsig *packet.Signature, priv *packet.PrivateKey, digest []byte) (err error) {
	sig := (*Signature)(unsafe.Pointer(pgpsig))
	var config *packet.Config
	switch priv.PubKeyAlgo {
	case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSASignOnly:
		sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
		sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
	case packet.PubKeyAlgoDSA:
		dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)

		r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
		if err == nil {
			sig.DSASigR.bytes = r.Bytes()
			sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
			sig.DSASigS.bytes = s.Bytes()
			sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
		}
	default:
		err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
	}

	return
}
예제 #18
0
// Sign signs a dns.Msg. It fills the signature with the appropriate data.
// The SIG record should have the SignerName, KeyTag, Algorithm, Inception
// and Expiration set.
func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) {
	if k == nil {
		return nil, ErrPrivKey
	}
	if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
		return nil, ErrKey
	}
	rr.Header().Rrtype = TypeSIG
	rr.Header().Class = ClassANY
	rr.Header().Ttl = 0
	rr.Header().Name = "."
	rr.OrigTtl = 0
	rr.TypeCovered = 0
	rr.Labels = 0

	buflen := m.Len() + rr.len()
	switch k := k.(type) {
	case *rsa.PrivateKey:
		buflen += len(k.N.Bytes())
	case *dsa.PrivateKey:
		buflen += 40
	case *ecdsa.PrivateKey:
		buflen += 96
	default:
		return nil, ErrPrivKey
	}
	buf := make([]byte, m.Len()+rr.len()+buflen)
	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)]
	var hash crypto.Hash
	switch rr.Algorithm {
	case DSA, RSASHA1:
		hash = crypto.SHA1
	case RSASHA256, ECDSAP256SHA256:
		hash = crypto.SHA256
	case ECDSAP384SHA384:
		hash = crypto.SHA384
	case RSASHA512:
		hash = crypto.SHA512
	default:
		return nil, ErrAlg
	}
	hasher := hash.New()
	// Write SIG rdata
	hasher.Write(buf[len(mbuf)+1+2+2+4+2:])
	// Write message
	hasher.Write(buf[:len(mbuf)])
	hashed := hasher.Sum(nil)

	var sig []byte
	switch p := k.(type) {
	case *dsa.PrivateKey:
		t := byte((len(p.PublicKey.Y.Bytes()) - 64) / 8)
		r1, s1, err := dsa.Sign(rand.Reader, p, hashed)
		if err != nil {
			return nil, err
		}
		sig = make([]byte, 0, 1+len(r1.Bytes())+len(s1.Bytes()))
		sig = append(sig, t)
		sig = append(sig, r1.Bytes()...)
		sig = append(sig, s1.Bytes()...)
	case *rsa.PrivateKey:
		sig, err = rsa.SignPKCS1v15(rand.Reader, p, hash, hashed)
		if err != nil {
			return nil, err
		}
	case *ecdsa.PrivateKey:
		r1, s1, err := ecdsa.Sign(rand.Reader, p, hashed)
		if err != nil {
			return nil, err
		}
		sig = r1.Bytes()
		sig = append(sig, s1.Bytes()...)
	default:
		return nil, ErrAlg
	}
	rr.Signature = unpackBase64(sig)
	buf = append(buf, sig...)
	if len(buf) > int(^uint16(0)) {
		return nil, ErrBuf
	}
	// Adjust sig data length
	rdoff := len(mbuf) + 1 + 2 + 2 + 4
	rdlen, _ := unpackUint16(buf, rdoff)
	rdlen += uint16(len(sig))
	buf[rdoff], buf[rdoff+1] = packUint16(rdlen)
	// Adjust additional count
	adc, _ := unpackUint16(buf, 10)
	adc += 1
	buf[10], buf[11] = packUint16(adc)
	return buf, nil
}
예제 #19
0
// Sign signs an RRSet. The signature needs to be filled in with
// the values: Inception, Expiration, KeyTag, SignerName and Algorithm.
// The rest is copied from the RRset. Sign returns true when the signing went OK,
// otherwise false.
// There is no check if RRSet is a proper (RFC 2181) RRSet.
// If OrigTTL is non zero, it is used as-is, otherwise the TTL of the RRset
// is used as the OrigTTL.
func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
	if k == nil {
		return ErrPrivKey
	}
	// s.Inception and s.Expiration may be 0 (rollover etc.), the rest must be set
	if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
		return ErrKey
	}

	rr.Hdr.Rrtype = TypeRRSIG
	rr.Hdr.Name = rrset[0].Header().Name
	rr.Hdr.Class = rrset[0].Header().Class
	if rr.OrigTtl == 0 { // If set don't override
		rr.OrigTtl = rrset[0].Header().Ttl
	}
	rr.TypeCovered = rrset[0].Header().Rrtype
	rr.Labels = uint8(CountLabel(rrset[0].Header().Name))

	if strings.HasPrefix(rrset[0].Header().Name, "*") {
		rr.Labels-- // wildcard, remove from label count
	}

	sigwire := new(rrsigWireFmt)
	sigwire.TypeCovered = rr.TypeCovered
	sigwire.Algorithm = rr.Algorithm
	sigwire.Labels = rr.Labels
	sigwire.OrigTtl = rr.OrigTtl
	sigwire.Expiration = rr.Expiration
	sigwire.Inception = rr.Inception
	sigwire.KeyTag = rr.KeyTag
	// For signing, lowercase this name
	sigwire.SignerName = strings.ToLower(rr.SignerName)

	// Create the desired binary blob
	signdata := make([]byte, DefaultMsgSize)
	n, err := PackStruct(sigwire, signdata, 0)
	if err != nil {
		return err
	}
	signdata = signdata[:n]
	wire, err := rawSignatureData(rrset, rr)
	if err != nil {
		return err
	}
	signdata = append(signdata, wire...)

	var sighash []byte
	var h hash.Hash
	var ch crypto.Hash // Only need for RSA
	var intlen int
	switch rr.Algorithm {
	case DSA, DSANSEC3SHA1:
		// Implicit in the ParameterSizes
	case RSASHA1, RSASHA1NSEC3SHA1:
		h = sha1.New()
		ch = crypto.SHA1
	case RSASHA256, ECDSAP256SHA256:
		h = sha256.New()
		ch = crypto.SHA256
		intlen = 32
	case ECDSAP384SHA384:
		h = sha512.New384()
		intlen = 48
	case RSASHA512:
		h = sha512.New()
		ch = crypto.SHA512
	case RSAMD5:
		fallthrough // Deprecated in RFC 6725
	default:
		return ErrAlg
	}
	io.WriteString(h, string(signdata))
	sighash = h.Sum(nil)

	switch p := k.(type) {
	case *dsa.PrivateKey:
		r1, s1, err := dsa.Sign(rand.Reader, p, sighash)
		if err != nil {
			return err
		}
		signature := []byte{0x4D} // T value, here the ASCII M for Miek (not used in DNSSEC)
		signature = append(signature, intToBytes(r1, 20)...)
		signature = append(signature, intToBytes(s1, 20)...)
		rr.Signature = toBase64(signature)
	case *rsa.PrivateKey:
		// We can use nil as rand.Reader here (says AGL)
		signature, err := rsa.SignPKCS1v15(nil, p, ch, sighash)
		if err != nil {
			return err
		}
		rr.Signature = toBase64(signature)
	case *ecdsa.PrivateKey:
		r1, s1, err := ecdsa.Sign(rand.Reader, p, sighash)
		if err != nil {
			return err
		}
		signature := intToBytes(r1, intlen)
		signature = append(signature, intToBytes(s1, intlen)...)
		rr.Signature = toBase64(signature)
	default:
		// Not given the correct key
		return ErrKeyAlg
	}
	return nil
}
예제 #20
0
파일: dnssec.go 프로젝트: wallrat/dns
// Sign signs an RRSet. The signature needs to be filled in with
// the values: Inception, Expiration, KeyTag, SignerName and Algorithm.
// The rest is copied from the RRset. Sign returns true when the signing went OK,
// otherwise false.
// The signature data in the RRSIG is filled by this method.
// There is no check if RRSet is a proper (RFC 2181) RRSet.
func (s *RR_RRSIG) Sign(k PrivateKey, rrset []RR) error {
	if k == nil {
		return ErrPrivKey
	}
	// s.Inception and s.Expiration may be 0 (rollover etc.), the rest must be set
	if s.KeyTag == 0 || len(s.SignerName) == 0 || s.Algorithm == 0 {
		return ErrKey
	}

	s.Hdr.Rrtype = TypeRRSIG
	s.Hdr.Name = rrset[0].Header().Name
	s.Hdr.Class = rrset[0].Header().Class
	s.OrigTtl = rrset[0].Header().Ttl
	s.TypeCovered = rrset[0].Header().Rrtype
	s.TypeCovered = rrset[0].Header().Rrtype
	s.Labels, _, _ = IsDomainName(rrset[0].Header().Name)

	if strings.HasPrefix(rrset[0].Header().Name, "*") {
		s.Labels-- // wildcard, remove from label count
	}

	sigwire := new(rrsigWireFmt)
	sigwire.TypeCovered = s.TypeCovered
	sigwire.Algorithm = s.Algorithm
	sigwire.Labels = s.Labels
	sigwire.OrigTtl = s.OrigTtl
	sigwire.Expiration = s.Expiration
	sigwire.Inception = s.Inception
	sigwire.KeyTag = s.KeyTag
	// For signing, lowercase this name
	sigwire.SignerName = strings.ToLower(s.SignerName)

	// Create the desired binary blob
	signdata := make([]byte, DefaultMsgSize)
	n, ok := PackStruct(sigwire, signdata, 0)
	if !ok {
		return ErrPack
	}
	signdata = signdata[:n]
	wire := rawSignatureData(rrset, s)
	if wire == nil {
		return ErrSigGen
	}
	signdata = append(signdata, wire...)

	var sighash []byte
	var h hash.Hash
	var ch crypto.Hash // Only need for RSA
	switch s.Algorithm {
	case DSA, DSANSEC3SHA1:
		// Implicit in the ParameterSizes
	case RSAMD5:
		h = md5.New()
		ch = crypto.MD5
	case RSASHA1, RSASHA1NSEC3SHA1:
		h = sha1.New()
		ch = crypto.SHA1
	case RSASHA256, ECDSAP256SHA256:
		h = sha256.New()
		ch = crypto.SHA256
	case ECDSAP384SHA384:
		h = sha512.New384()
	case RSASHA512:
		h = sha512.New()
		ch = crypto.SHA512
	default:
		return ErrAlg
	}
	io.WriteString(h, string(signdata))
	sighash = h.Sum(nil)

	switch p := k.(type) {
	case *dsa.PrivateKey:
		r1, s1, err := dsa.Sign(rand.Reader, p, sighash)
		if err != nil {
			return err
		}
		signature := []byte{0x4D} // T value, here the ASCII M for Miek (not used in DNSSEC)
		signature = append(signature, r1.Bytes()...)
		signature = append(signature, s1.Bytes()...)
		s.Signature = unpackBase64(signature)
	case *rsa.PrivateKey:
		signature, err := rsa.SignPKCS1v15(rand.Reader, p, ch, sighash)
		if err != nil {
			return err
		}
		s.Signature = unpackBase64(signature)
	case *ecdsa.PrivateKey:
		r1, s1, err := ecdsa.Sign(rand.Reader, p, sighash)
		if err != nil {
			return err
		}
		signature := r1.Bytes()
		signature = append(signature, s1.Bytes()...)
		s.Signature = unpackBase64(signature)
	default:
		// Not given the correct key
		return ErrKeyAlg
	}
	return nil
}