From 3fd8a8eef602d47ce4a10151394d66520324a4bd Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Thu, 22 Jan 2015 21:48:54 -0800 Subject: [PATCH 1/3] Fix: RSA key export and its test --- dnssec_test.go | 23 ++++++++++++++++------- keygen.go | 5 ++--- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/dnssec_test.go b/dnssec_test.go index f6263d50..2471a3f5 100644 --- a/dnssec_test.go +++ b/dnssec_test.go @@ -249,12 +249,13 @@ func Test65534(t *testing.T) { } func TestDnskey(t *testing.T) { - // f, _ := os.Open("t/Kmiek.nl.+010+05240.key") - pubkey, _ := ReadRR(strings.NewReader(` + pubkey, err := ReadRR(strings.NewReader(` miek.nl. IN DNSKEY 256 3 10 AwEAAZuMCu2FdugHkTrXYgl5qixvcDw1aDDlvL46/xJKbHBAHY16fNUb2b65cwko2Js/aJxUYJbZk5dwCDZxYfrfbZVtDPQuc3o8QaChVxC7/JYz2AHc9qHvqQ1j4VrH71RWINlQo6VYjzN/BGpMhOZoZOEwzp1HfsOE3lNYcoWU1smL ;{id = 5240 (zsk), size = 1024b} `), "Kmiek.nl.+010+05240.key") - privkey, _ := pubkey.(*DNSKEY).ReadPrivateKey(strings.NewReader(` -Private-key-format: v1.2 + if err != nil { + t.Fatal(err) + } + privStr := `Private-key-format: v1.3 Algorithm: 10 (RSASHA512) Modulus: m4wK7YV26AeROtdiCXmqLG9wPDVoMOW8vjr/EkpscEAdjXp81RvZvrlzCSjYmz9onFRgltmTl3AINnFh+t9tlW0M9C5zejxBoKFXELv8ljPYAdz2oe+pDWPhWsfvVFYg2VCjpViPM38EakyE5mhk4TDOnUd+w4TeU1hyhZTWyYs= PublicExponent: AQAB @@ -264,13 +265,21 @@ Prime2: xA1bF8M0RTIQ6+A11AoVG6GIR/aPGg5sogRkIZ7ID/sF6g9HMVU/CM2TqVEBJLRPp73cv6Ze Exponent1: xzkblyZ96bGYxTVZm2/vHMOXswod4KWIyMoOepK6B/ZPcZoIT6omLCgtypWtwHLfqyCz3MK51Nc0G2EGzg8rFQ== Exponent2: Pu5+mCEb7T5F+kFNZhQadHUklt0JUHbi3hsEvVoHpEGSw3BGDQrtIflDde0/rbWHgDPM4WQY+hscd8UuTXrvLw== Coefficient: UuRoNqe7YHnKmQzE6iDWKTMIWTuoqqrFAmXPmKQnC+Y+BQzOVEHUo9bXdDnoI9hzXP1gf8zENMYwYLeWpuYlFQ== -`), "Kmiek.nl.+010+05240.private") +` + privkey, err := pubkey.(*DNSKEY).ReadPrivateKey(strings.NewReader(privStr), + "Kmiek.nl.+010+05240.private") + if err != nil { + t.Fatal(err) + } if pubkey.(*DNSKEY).PublicKey != "AwEAAZuMCu2FdugHkTrXYgl5qixvcDw1aDDlvL46/xJKbHBAHY16fNUb2b65cwko2Js/aJxUYJbZk5dwCDZxYfrfbZVtDPQuc3o8QaChVxC7/JYz2AHc9qHvqQ1j4VrH71RWINlQo6VYjzN/BGpMhOZoZOEwzp1HfsOE3lNYcoWU1smL" { t.Log("pubkey is not what we've read") t.Fail() } - // Coefficient looks fishy... - t.Logf("%s", pubkey.(*DNSKEY).PrivateKeyString(privkey)) + if pubkey.(*DNSKEY).PrivateKeyString(privkey) != privStr { + t.Log("privkey is not what we've read") + t.Logf("%v", pubkey.(*DNSKEY).PrivateKeyString(privkey)) + t.Fail() + } } func TestTag(t *testing.T) { diff --git a/keygen.go b/keygen.go index dfe328ec..8d86cb0a 100644 --- a/keygen.go +++ b/keygen.go @@ -103,12 +103,11 @@ func (r *DNSKEY) PrivateKeyString(p PrivateKey) (s string) { // Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm // and from: http://code.google.com/p/go/issues/detail?id=987 one := big.NewInt(1) - minusone := big.NewInt(-1) p_1 := big.NewInt(0).Sub(t.Primes[0], one) q_1 := big.NewInt(0).Sub(t.Primes[1], one) exp1 := big.NewInt(0).Mod(t.D, p_1) exp2 := big.NewInt(0).Mod(t.D, q_1) - coeff := big.NewInt(0).Exp(t.Primes[1], minusone, t.Primes[0]) + coeff := big.NewInt(0).ModInverse(t.Primes[1], t.Primes[0]) exponent1 := toBase64(exp1.Bytes()) exponent2 := toBase64(exp2.Bytes()) @@ -116,7 +115,7 @@ func (r *DNSKEY) PrivateKeyString(p PrivateKey) (s string) { s = _FORMAT + "Algorithm: " + algorithm + "\n" + - "Modules: " + modulus + "\n" + + "Modulus: " + modulus + "\n" + "PublicExponent: " + publicExponent + "\n" + "PrivateExponent: " + privateExponent + "\n" + "Prime1: " + prime1 + "\n" + From e9faa971b320961a208a7ab53c7805d4f280f809 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 23 Jan 2015 13:04:29 -0800 Subject: [PATCH 2/3] Refactor the DNSSEC private key code Now PrivateKey is an interface exposing Sign() and String(). Common implementations are wrappers for {rsa|dsa|ecdsa}.PrivateKey but this allows for custom signers, and abstracts away the private-ops code to a single place. --- dnssec.go | 85 ++++++---------------------- dnssec_test.go | 3 +- keygen.go | 146 +++++++++++++++++++++++++++++++++++-------------- kscan.go | 49 ++++++++--------- parse_test.go | 4 +- sig0.go | 34 ++---------- 6 files changed, 151 insertions(+), 170 deletions(-) diff --git a/dnssec.go b/dnssec.go index d1c2ae62..7e1ba851 100644 --- a/dnssec.go +++ b/dnssec.go @@ -20,7 +20,6 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/md5" - "crypto/rand" "crypto/rsa" "crypto/sha1" "crypto/sha256" @@ -256,63 +255,36 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error { } 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 + // TODO: this seems bugged, will panic 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 + _, err = h.Write(signdata) + if err != nil { + return err } + sighash := h.Sum(nil) + + signature, err := k.Sign(sighash, rr.Algorithm) + if err != nil { + return err + } + rr.Signature = toBase64(signature) + return nil } @@ -405,7 +377,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error { sighash := h.Sum(nil) return rsa.VerifyPKCS1v15(pubkey, ch, sighash, sigbuf) case ECDSAP256SHA256, ECDSAP384SHA384: - pubkey := k.publicKeyCurve() + pubkey := k.publicKeyECDSA() if pubkey == nil { return ErrKey } @@ -458,31 +430,6 @@ func (s *RRSIG) sigBuf() []byte { return sigbuf } -// setPublicKeyInPrivate sets the public key in the private key. -func (k *DNSKEY) setPublicKeyInPrivate(p PrivateKey) bool { - switch t := p.(type) { - case *dsa.PrivateKey: - x := k.publicKeyDSA() - if x == nil { - return false - } - t.PublicKey = *x - case *rsa.PrivateKey: - x := k.publicKeyRSA() - if x == nil { - return false - } - t.PublicKey = *x - case *ecdsa.PrivateKey: - x := k.publicKeyCurve() - if x == nil { - return false - } - t.PublicKey = *x - } - return true -} - // publicKeyRSA returns the RSA public key from a DNSKEY record. func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey { keybuf, err := fromBase64([]byte(k.PublicKey)) @@ -521,8 +468,8 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey { return pubkey } -// publicKeyCurve returns the Curve public key from the DNSKEY record. -func (k *DNSKEY) publicKeyCurve() *ecdsa.PublicKey { +// publicKeyECDSA returns the Curve public key from the DNSKEY record. +func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey { keybuf, err := fromBase64([]byte(k.PublicKey)) if err != nil { return nil @@ -585,7 +532,7 @@ func (k *DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool { } // Set the public key for Elliptic Curves -func (k *DNSKEY) setPublicKeyCurve(_X, _Y *big.Int) bool { +func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool { if _X == nil || _Y == nil { return false } diff --git a/dnssec_test.go b/dnssec_test.go index 2471a3f5..76f56c24 100644 --- a/dnssec_test.go +++ b/dnssec_test.go @@ -1,7 +1,6 @@ package dns import ( - "crypto/rsa" "reflect" "strings" "testing" @@ -389,7 +388,7 @@ Activate: 20110302104537` t.Fail() } switch priv := p.(type) { - case *rsa.PrivateKey: + case *RSAPrivateKey: if 65537 != priv.PublicKey.E { t.Log("exponenent should be 65537") t.Fail() diff --git a/keygen.go b/keygen.go index 8d86cb0a..492d88e6 100644 --- a/keygen.go +++ b/keygen.go @@ -1,6 +1,7 @@ package dns import ( + "crypto" "crypto/dsa" "crypto/ecdsa" "crypto/elliptic" @@ -12,9 +13,10 @@ import ( const _FORMAT = "Private-key-format: v1.3\n" -// Empty interface that is used as a wrapper around all possible -// private key implementations from the crypto package. -type PrivateKey interface{} +type PrivateKey interface { + Sign([]byte, uint8) ([]byte, error) + String(uint8) string +} // Generate generates a DNSKEY of the given bit size. // The public part is put inside the DNSKEY record. @@ -59,14 +61,14 @@ func (r *DNSKEY) Generate(bits int) (PrivateKey, error) { return nil, err } r.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y) - return priv, nil + return (*DSAPrivateKey)(priv), nil case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1: priv, err := rsa.GenerateKey(rand.Reader, bits) if err != nil { return nil, err } r.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N) - return priv, nil + return (*RSAPrivateKey)(priv), nil case ECDSAP256SHA256, ECDSAP384SHA384: var c elliptic.Curve switch r.Algorithm { @@ -79,41 +81,61 @@ func (r *DNSKEY) Generate(bits int) (PrivateKey, error) { if err != nil { return nil, err } - r.setPublicKeyCurve(priv.PublicKey.X, priv.PublicKey.Y) - return priv, nil + r.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y) + return (*ECDSAPrivateKey)(priv), nil default: return nil, ErrAlg } - return nil, nil // Dummy return } -// PrivateKeyString converts a PrivateKey to a string. This -// string has the same format as the private-key-file of BIND9 (Private-key-format: v1.3). -// It needs some info from the key (hashing, keytag), so its a method of the DNSKEY. -func (r *DNSKEY) PrivateKeyString(p PrivateKey) (s string) { - switch t := p.(type) { - case *rsa.PrivateKey: - algorithm := strconv.Itoa(int(r.Algorithm)) + " (" + AlgorithmToString[r.Algorithm] + ")" - modulus := toBase64(t.PublicKey.N.Bytes()) - e := big.NewInt(int64(t.PublicKey.E)) +// PrivateKeyString converts a PrivateKey to a string. This string has the same +// format as the private-key-file of BIND9 (Private-key-format: v1.3). +// It needs some info from the key (the algorithm), so its a method of the +// DNSKEY and calls PrivateKey.String(alg). +func (r *DNSKEY) PrivateKeyString(p PrivateKey) string { + return p.String(r.Algorithm) +} + +type RSAPrivateKey rsa.PrivateKey + +func (p *RSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) { + var hash crypto.Hash + switch alg { + case RSASHA1, RSASHA1NSEC3SHA1: + hash = crypto.SHA1 + case RSASHA256: + hash = crypto.SHA256 + case RSASHA512: + hash = crypto.SHA512 + default: + return nil, ErrAlg + } + return rsa.SignPKCS1v15(nil, (*rsa.PrivateKey)(p), hash, hashed) +} + +func (p *RSAPrivateKey) String(alg uint8) string { + if true { + algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")" + modulus := toBase64(p.PublicKey.N.Bytes()) + e := big.NewInt(int64(p.PublicKey.E)) publicExponent := toBase64(e.Bytes()) - privateExponent := toBase64(t.D.Bytes()) - prime1 := toBase64(t.Primes[0].Bytes()) - prime2 := toBase64(t.Primes[1].Bytes()) + privateExponent := toBase64(p.D.Bytes()) + prime1 := toBase64(p.Primes[0].Bytes()) + prime2 := toBase64(p.Primes[1].Bytes()) // Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm // and from: http://code.google.com/p/go/issues/detail?id=987 one := big.NewInt(1) - p_1 := big.NewInt(0).Sub(t.Primes[0], one) - q_1 := big.NewInt(0).Sub(t.Primes[1], one) - exp1 := big.NewInt(0).Mod(t.D, p_1) - exp2 := big.NewInt(0).Mod(t.D, q_1) - coeff := big.NewInt(0).ModInverse(t.Primes[1], t.Primes[0]) + p_1 := big.NewInt(0).Sub(p.Primes[0], one) + q_1 := big.NewInt(0).Sub(p.Primes[1], one) + exp1 := big.NewInt(0).Mod(p.D, p_1) + exp2 := big.NewInt(0).Mod(p.D, q_1) + coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0]) exponent1 := toBase64(exp1.Bytes()) exponent2 := toBase64(exp2.Bytes()) coefficient := toBase64(coeff.Bytes()) - s = _FORMAT + + return _FORMAT + "Algorithm: " + algorithm + "\n" + "Modulus: " + modulus + "\n" + "PublicExponent: " + publicExponent + "\n" + @@ -123,28 +145,71 @@ func (r *DNSKEY) PrivateKeyString(p PrivateKey) (s string) { "Exponent1: " + exponent1 + "\n" + "Exponent2: " + exponent2 + "\n" + "Coefficient: " + coefficient + "\n" - case *ecdsa.PrivateKey: - algorithm := strconv.Itoa(int(r.Algorithm)) + " (" + AlgorithmToString[r.Algorithm] + ")" + } +} + +type ECDSAPrivateKey ecdsa.PrivateKey + +func (p *ECDSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) { + var intlen int + switch alg { + case ECDSAP256SHA256: + intlen = 32 + case ECDSAP384SHA384: + intlen = 48 + default: + return nil, ErrAlg + } + r1, s1, err := ecdsa.Sign(rand.Reader, (*ecdsa.PrivateKey)(p), hashed) + if err != nil { + return nil, err + } + signature := intToBytes(r1, intlen) + signature = append(signature, intToBytes(s1, intlen)...) + return signature, nil +} + +func (p *ECDSAPrivateKey) String(alg uint8) string { + if true { + algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")" var intlen int - switch r.Algorithm { + switch alg { case ECDSAP256SHA256: intlen = 32 case ECDSAP384SHA384: intlen = 48 } - private := toBase64(intToBytes(t.D, intlen)) - s = _FORMAT + + private := toBase64(intToBytes(p.D, intlen)) + return _FORMAT + "Algorithm: " + algorithm + "\n" + "PrivateKey: " + private + "\n" - case *dsa.PrivateKey: - algorithm := strconv.Itoa(int(r.Algorithm)) + " (" + AlgorithmToString[r.Algorithm] + ")" - T := divRoundUp(divRoundUp(t.PublicKey.Parameters.G.BitLen(), 8)-64, 8) - prime := toBase64(intToBytes(t.PublicKey.Parameters.P, 64+T*8)) - subprime := toBase64(intToBytes(t.PublicKey.Parameters.Q, 20)) - base := toBase64(intToBytes(t.PublicKey.Parameters.G, 64+T*8)) - priv := toBase64(intToBytes(t.X, 20)) - pub := toBase64(intToBytes(t.PublicKey.Y, 64+T*8)) - s = _FORMAT + + } +} + +type DSAPrivateKey dsa.PrivateKey + +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 +} + +func (p *DSAPrivateKey) String(alg uint8) string { + if true { + algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")" + T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8) + prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8)) + subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20)) + base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8)) + priv := toBase64(intToBytes(p.X, 20)) + pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8)) + return _FORMAT + "Algorithm: " + algorithm + "\n" + "Prime(p): " + prime + "\n" + "Subprime(q): " + subprime + "\n" + @@ -152,5 +217,4 @@ func (r *DNSKEY) PrivateKeyString(p PrivateKey) (s string) { "Private_value(x): " + priv + "\n" + "Public_value(y): " + pub + "\n" } - return } diff --git a/kscan.go b/kscan.go index c48ca2d2..ce52b877 100644 --- a/kscan.go +++ b/kscan.go @@ -18,8 +18,8 @@ func (k *DNSKEY) NewPrivateKey(s string) (PrivateKey, error) { // ReadPrivateKey reads a private key from the io.Reader q. The string file is // only used in error reporting. -// The public key must be -// known, because some cryptographic algorithms embed the public inside the privatekey. +// The public key must be known, because some cryptographic algorithms embed +// the public inside the privatekey. func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) { m, e := parseKey(q, file) if m == nil { @@ -34,14 +34,16 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) { // TODO(mg): check if the pubkey matches the private key switch m["algorithm"] { case "3 (DSA)": - p, e := readPrivateKeyDSA(m) + priv, e := readPrivateKeyDSA(m) if e != nil { return nil, e } - if !k.setPublicKeyInPrivate(p) { + pub := k.publicKeyDSA() + if pub == nil { return nil, ErrKey } - return p, e + priv.PublicKey = *pub + return (*DSAPrivateKey)(priv), e case "1 (RSAMD5)": fallthrough case "5 (RSASHA1)": @@ -51,38 +53,38 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) { case "8 (RSASHA256)": fallthrough case "10 (RSASHA512)": - p, e := readPrivateKeyRSA(m) + priv, e := readPrivateKeyRSA(m) if e != nil { return nil, e } - if !k.setPublicKeyInPrivate(p) { + pub := k.publicKeyRSA() + if pub == nil { return nil, ErrKey } - return p, e + priv.PublicKey = *pub + return (*RSAPrivateKey)(priv), e case "12 (ECC-GOST)": - p, e := readPrivateKeyGOST(m) - if e != nil { - return nil, e - } - // setPublicKeyInPrivate(p) - return p, e + return nil, ErrPrivKey case "13 (ECDSAP256SHA256)": fallthrough case "14 (ECDSAP384SHA384)": - p, e := readPrivateKeyECDSA(m) + priv, e := readPrivateKeyECDSA(m) if e != nil { return nil, e } - if !k.setPublicKeyInPrivate(p) { + pub := k.publicKeyECDSA() + if pub == nil { return nil, ErrKey } - return p, e + priv.PublicKey = *pub + return (*ECDSAPrivateKey)(priv), e + default: + return nil, ErrPrivKey } - return nil, ErrPrivKey } // Read a private key (file) string and create a public key. Return the private key. -func readPrivateKeyRSA(m map[string]string) (PrivateKey, error) { +func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) { p := new(rsa.PrivateKey) p.Primes = []*big.Int{nil, nil} for k, v := range m { @@ -119,7 +121,7 @@ func readPrivateKeyRSA(m map[string]string) (PrivateKey, error) { return p, nil } -func readPrivateKeyDSA(m map[string]string) (PrivateKey, error) { +func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) { p := new(dsa.PrivateKey) p.X = big.NewInt(0) for k, v := range m { @@ -137,7 +139,7 @@ func readPrivateKeyDSA(m map[string]string) (PrivateKey, error) { return p, nil } -func readPrivateKeyECDSA(m map[string]string) (PrivateKey, error) { +func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) { p := new(ecdsa.PrivateKey) p.D = big.NewInt(0) // TODO: validate that the required flags are present @@ -156,11 +158,6 @@ func readPrivateKeyECDSA(m map[string]string) (PrivateKey, error) { return p, nil } -func readPrivateKeyGOST(m map[string]string) (PrivateKey, error) { - // TODO(miek) - return nil, nil -} - // parseKey reads a private key from r. It returns a map[string]string, // with the key-value pairs, or an error when the file is not correct. func parseKey(r io.Reader, file string) (map[string]string, error) { diff --git a/parse_test.go b/parse_test.go index c9c4c519..ab0a2494 100644 --- a/parse_test.go +++ b/parse_test.go @@ -1265,8 +1265,8 @@ func TestNewPrivateKey(t *testing.T) { } switch newPrivKey := newPrivKey.(type) { - case *rsa.PrivateKey: - newPrivKey.Precompute() + case *RSAPrivateKey: + (*rsa.PrivateKey)(newPrivKey).Precompute() } if !reflect.DeepEqual(privkey, newPrivKey) { diff --git a/sig0.go b/sig0.go index d96b31be..bef88cf9 100644 --- a/sig0.go +++ b/sig0.go @@ -19,7 +19,6 @@ import ( "crypto" "crypto/dsa" "crypto/ecdsa" - "crypto/rand" "crypto/rsa" "math/big" "strings" @@ -58,16 +57,13 @@ func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) { } buf = buf[:off:cap(buf)] var hash crypto.Hash - var intlen int switch rr.Algorithm { case DSA, RSASHA1: hash = crypto.SHA1 case RSASHA256, ECDSAP256SHA256: hash = crypto.SHA256 - intlen = 32 case ECDSAP384SHA384: hash = crypto.SHA384 - intlen = 48 case RSASHA512: hash = crypto.SHA512 default: @@ -80,31 +76,9 @@ func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) { hasher.Write(buf[:len(mbuf)]) hashed := hasher.Sum(nil) - var sig []byte - switch p := k.(type) { - case *dsa.PrivateKey: - t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8) - r1, s1, err := dsa.Sign(rand.Reader, p, hashed) - if err != nil { - return nil, err - } - sig = append(sig, byte(t)) - sig = append(sig, intToBytes(r1, 20)...) - sig = append(sig, intToBytes(s1, 20)...) - 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 = intToBytes(r1, intlen) - sig = append(sig, intToBytes(s1, intlen)...) - default: - return nil, ErrAlg + sig, err := k.Sign(hashed, rr.Algorithm) + if err != nil { + return nil, err } rr.Signature = toBase64(sig) buf = append(buf, sig...) @@ -246,7 +220,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error { return rsa.VerifyPKCS1v15(pk, hash, hashed, sig) } case ECDSAP256SHA256, ECDSAP384SHA384: - pk := k.publicKeyCurve() + pk := k.publicKeyECDSA() r := big.NewInt(0) r.SetBytes(sig[:len(sig)/2]) s := big.NewInt(0) From 3035815b295539a8b1d804b65693b9181c6386e9 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 23 Jan 2015 13:06:08 -0800 Subject: [PATCH 3/3] Reorder DNSSEC code --- dnssec.go | 75 ------------ dnssec_keygen.go | 155 ++++++++++++++++++++++++ kscan.go => dnssec_keyscan.go | 0 dnssec_privkey.go | 143 ++++++++++++++++++++++ keygen.go | 220 ---------------------------------- 5 files changed, 298 insertions(+), 295 deletions(-) create mode 100644 dnssec_keygen.go rename kscan.go => dnssec_keyscan.go (100%) create mode 100644 dnssec_privkey.go delete mode 100644 keygen.go diff --git a/dnssec.go b/dnssec.go index 7e1ba851..4af0faeb 100644 --- a/dnssec.go +++ b/dnssec.go @@ -520,81 +520,6 @@ func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey { return pubkey } -// Set the public key (the value E and N) -func (k *DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool { - if _E == 0 || _N == nil { - return false - } - buf := exponentToBuf(_E) - buf = append(buf, _N.Bytes()...) - k.PublicKey = toBase64(buf) - return true -} - -// Set the public key for Elliptic Curves -func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool { - if _X == nil || _Y == nil { - return false - } - var intlen int - switch k.Algorithm { - case ECDSAP256SHA256: - intlen = 32 - case ECDSAP384SHA384: - intlen = 48 - } - k.PublicKey = toBase64(curveToBuf(_X, _Y, intlen)) - return true -} - -// Set the public key for DSA -func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool { - if _Q == nil || _P == nil || _G == nil || _Y == nil { - return false - } - buf := dsaToBuf(_Q, _P, _G, _Y) - k.PublicKey = toBase64(buf) - return true -} - -// Set the public key (the values E and N) for RSA -// RFC 3110: Section 2. RSA Public KEY Resource Records -func exponentToBuf(_E int) []byte { - var buf []byte - i := big.NewInt(int64(_E)) - if len(i.Bytes()) < 256 { - buf = make([]byte, 1) - buf[0] = uint8(len(i.Bytes())) - } else { - buf = make([]byte, 3) - buf[0] = 0 - buf[1] = uint8(len(i.Bytes()) >> 8) - buf[2] = uint8(len(i.Bytes())) - } - buf = append(buf, i.Bytes()...) - return buf -} - -// Set the public key for X and Y for Curve. The two -// values are just concatenated. -func curveToBuf(_X, _Y *big.Int, intlen int) []byte { - buf := intToBytes(_X, intlen) - buf = append(buf, intToBytes(_Y, intlen)...) - return buf -} - -// Set the public key for X and Y for Curve. The two -// values are just concatenated. -func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte { - t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8) - buf := []byte{byte(t)} - buf = append(buf, intToBytes(_Q, 20)...) - buf = append(buf, intToBytes(_P, 64+t*8)...) - buf = append(buf, intToBytes(_G, 64+t*8)...) - buf = append(buf, intToBytes(_Y, 64+t*8)...) - return buf -} - type wireSlice [][]byte func (p wireSlice) Len() int { return len(p) } diff --git a/dnssec_keygen.go b/dnssec_keygen.go new file mode 100644 index 00000000..f49018c5 --- /dev/null +++ b/dnssec_keygen.go @@ -0,0 +1,155 @@ +package dns + +import ( + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "math/big" +) + +// Generate generates a DNSKEY of the given bit size. +// The public part is put inside the DNSKEY record. +// The Algorithm in the key must be set as this will define +// what kind of DNSKEY will be generated. +// The ECDSA algorithms imply a fixed keysize, in that case +// bits should be set to the size of the algorithm. +func (r *DNSKEY) Generate(bits int) (PrivateKey, error) { + switch r.Algorithm { + case DSA, DSANSEC3SHA1: + if bits != 1024 { + return nil, ErrKeySize + } + case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1: + if bits < 512 || bits > 4096 { + return nil, ErrKeySize + } + case RSASHA512: + if bits < 1024 || bits > 4096 { + return nil, ErrKeySize + } + case ECDSAP256SHA256: + if bits != 256 { + return nil, ErrKeySize + } + case ECDSAP384SHA384: + if bits != 384 { + return nil, ErrKeySize + } + } + + switch r.Algorithm { + case DSA, DSANSEC3SHA1: + params := new(dsa.Parameters) + if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil { + return nil, err + } + priv := new(dsa.PrivateKey) + priv.PublicKey.Parameters = *params + err := dsa.GenerateKey(priv, rand.Reader) + if err != nil { + return nil, err + } + r.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y) + return (*DSAPrivateKey)(priv), nil + case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1: + priv, err := rsa.GenerateKey(rand.Reader, bits) + if err != nil { + return nil, err + } + r.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N) + return (*RSAPrivateKey)(priv), nil + case ECDSAP256SHA256, ECDSAP384SHA384: + var c elliptic.Curve + switch r.Algorithm { + case ECDSAP256SHA256: + c = elliptic.P256() + case ECDSAP384SHA384: + c = elliptic.P384() + } + priv, err := ecdsa.GenerateKey(c, rand.Reader) + if err != nil { + return nil, err + } + r.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y) + return (*ECDSAPrivateKey)(priv), nil + default: + return nil, ErrAlg + } +} + +// Set the public key (the value E and N) +func (k *DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool { + if _E == 0 || _N == nil { + return false + } + buf := exponentToBuf(_E) + buf = append(buf, _N.Bytes()...) + k.PublicKey = toBase64(buf) + return true +} + +// Set the public key for Elliptic Curves +func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool { + if _X == nil || _Y == nil { + return false + } + var intlen int + switch k.Algorithm { + case ECDSAP256SHA256: + intlen = 32 + case ECDSAP384SHA384: + intlen = 48 + } + k.PublicKey = toBase64(curveToBuf(_X, _Y, intlen)) + return true +} + +// Set the public key for DSA +func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool { + if _Q == nil || _P == nil || _G == nil || _Y == nil { + return false + } + buf := dsaToBuf(_Q, _P, _G, _Y) + k.PublicKey = toBase64(buf) + return true +} + +// Set the public key (the values E and N) for RSA +// RFC 3110: Section 2. RSA Public KEY Resource Records +func exponentToBuf(_E int) []byte { + var buf []byte + i := big.NewInt(int64(_E)) + if len(i.Bytes()) < 256 { + buf = make([]byte, 1) + buf[0] = uint8(len(i.Bytes())) + } else { + buf = make([]byte, 3) + buf[0] = 0 + buf[1] = uint8(len(i.Bytes()) >> 8) + buf[2] = uint8(len(i.Bytes())) + } + buf = append(buf, i.Bytes()...) + return buf +} + +// Set the public key for X and Y for Curve. The two +// values are just concatenated. +func curveToBuf(_X, _Y *big.Int, intlen int) []byte { + buf := intToBytes(_X, intlen) + buf = append(buf, intToBytes(_Y, intlen)...) + return buf +} + +// Set the public key for X and Y for Curve. The two +// values are just concatenated. +func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte { + t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8) + buf := []byte{byte(t)} + buf = append(buf, intToBytes(_Q, 20)...) + buf = append(buf, intToBytes(_P, 64+t*8)...) + buf = append(buf, intToBytes(_G, 64+t*8)...) + buf = append(buf, intToBytes(_Y, 64+t*8)...) + return buf +} diff --git a/kscan.go b/dnssec_keyscan.go similarity index 100% rename from kscan.go rename to dnssec_keyscan.go diff --git a/dnssec_privkey.go b/dnssec_privkey.go new file mode 100644 index 00000000..955798a7 --- /dev/null +++ b/dnssec_privkey.go @@ -0,0 +1,143 @@ +package dns + +import ( + "crypto" + "crypto/dsa" + "crypto/ecdsa" + "crypto/rand" + "crypto/rsa" + "math/big" + "strconv" +) + +const _FORMAT = "Private-key-format: v1.3\n" + +type PrivateKey interface { + Sign([]byte, uint8) ([]byte, error) + String(uint8) string +} + +// PrivateKeyString converts a PrivateKey to a string. This string has the same +// format as the private-key-file of BIND9 (Private-key-format: v1.3). +// It needs some info from the key (the algorithm), so its a method of the +// DNSKEY and calls PrivateKey.String(alg). +func (r *DNSKEY) PrivateKeyString(p PrivateKey) string { + return p.String(r.Algorithm) +} + +type RSAPrivateKey rsa.PrivateKey + +func (p *RSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) { + var hash crypto.Hash + switch alg { + case RSASHA1, RSASHA1NSEC3SHA1: + hash = crypto.SHA1 + case RSASHA256: + hash = crypto.SHA256 + case RSASHA512: + hash = crypto.SHA512 + default: + return nil, ErrAlg + } + return rsa.SignPKCS1v15(nil, (*rsa.PrivateKey)(p), hash, hashed) +} + +func (p *RSAPrivateKey) String(alg uint8) string { + algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")" + modulus := toBase64(p.PublicKey.N.Bytes()) + e := big.NewInt(int64(p.PublicKey.E)) + publicExponent := toBase64(e.Bytes()) + privateExponent := toBase64(p.D.Bytes()) + prime1 := toBase64(p.Primes[0].Bytes()) + prime2 := toBase64(p.Primes[1].Bytes()) + // Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm + // and from: http://code.google.com/p/go/issues/detail?id=987 + one := big.NewInt(1) + p_1 := big.NewInt(0).Sub(p.Primes[0], one) + q_1 := big.NewInt(0).Sub(p.Primes[1], one) + exp1 := big.NewInt(0).Mod(p.D, p_1) + exp2 := big.NewInt(0).Mod(p.D, q_1) + coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0]) + + exponent1 := toBase64(exp1.Bytes()) + exponent2 := toBase64(exp2.Bytes()) + coefficient := toBase64(coeff.Bytes()) + + return _FORMAT + + "Algorithm: " + algorithm + "\n" + + "Modulus: " + modulus + "\n" + + "PublicExponent: " + publicExponent + "\n" + + "PrivateExponent: " + privateExponent + "\n" + + "Prime1: " + prime1 + "\n" + + "Prime2: " + prime2 + "\n" + + "Exponent1: " + exponent1 + "\n" + + "Exponent2: " + exponent2 + "\n" + + "Coefficient: " + coefficient + "\n" +} + +type ECDSAPrivateKey ecdsa.PrivateKey + +func (p *ECDSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) { + var intlen int + switch alg { + case ECDSAP256SHA256: + intlen = 32 + case ECDSAP384SHA384: + intlen = 48 + default: + return nil, ErrAlg + } + r1, s1, err := ecdsa.Sign(rand.Reader, (*ecdsa.PrivateKey)(p), hashed) + if err != nil { + return nil, err + } + signature := intToBytes(r1, intlen) + signature = append(signature, intToBytes(s1, intlen)...) + return signature, nil +} + +func (p *ECDSAPrivateKey) String(alg uint8) string { + algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")" + var intlen int + switch alg { + case ECDSAP256SHA256: + intlen = 32 + case ECDSAP384SHA384: + intlen = 48 + } + private := toBase64(intToBytes(p.D, intlen)) + return _FORMAT + + "Algorithm: " + algorithm + "\n" + + "PrivateKey: " + private + "\n" +} + +type DSAPrivateKey dsa.PrivateKey + +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 +} + +func (p *DSAPrivateKey) String(alg uint8) string { + algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")" + T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8) + prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8)) + subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20)) + base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8)) + priv := toBase64(intToBytes(p.X, 20)) + pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8)) + return _FORMAT + + "Algorithm: " + algorithm + "\n" + + "Prime(p): " + prime + "\n" + + "Subprime(q): " + subprime + "\n" + + "Base(g): " + base + "\n" + + "Private_value(x): " + priv + "\n" + + "Public_value(y): " + pub + "\n" +} diff --git a/keygen.go b/keygen.go deleted file mode 100644 index 492d88e6..00000000 --- a/keygen.go +++ /dev/null @@ -1,220 +0,0 @@ -package dns - -import ( - "crypto" - "crypto/dsa" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "math/big" - "strconv" -) - -const _FORMAT = "Private-key-format: v1.3\n" - -type PrivateKey interface { - Sign([]byte, uint8) ([]byte, error) - String(uint8) string -} - -// Generate generates a DNSKEY of the given bit size. -// The public part is put inside the DNSKEY record. -// The Algorithm in the key must be set as this will define -// what kind of DNSKEY will be generated. -// The ECDSA algorithms imply a fixed keysize, in that case -// bits should be set to the size of the algorithm. -func (r *DNSKEY) Generate(bits int) (PrivateKey, error) { - switch r.Algorithm { - case DSA, DSANSEC3SHA1: - if bits != 1024 { - return nil, ErrKeySize - } - case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1: - if bits < 512 || bits > 4096 { - return nil, ErrKeySize - } - case RSASHA512: - if bits < 1024 || bits > 4096 { - return nil, ErrKeySize - } - case ECDSAP256SHA256: - if bits != 256 { - return nil, ErrKeySize - } - case ECDSAP384SHA384: - if bits != 384 { - return nil, ErrKeySize - } - } - - switch r.Algorithm { - case DSA, DSANSEC3SHA1: - params := new(dsa.Parameters) - if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil { - return nil, err - } - priv := new(dsa.PrivateKey) - priv.PublicKey.Parameters = *params - err := dsa.GenerateKey(priv, rand.Reader) - if err != nil { - return nil, err - } - r.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y) - return (*DSAPrivateKey)(priv), nil - case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1: - priv, err := rsa.GenerateKey(rand.Reader, bits) - if err != nil { - return nil, err - } - r.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N) - return (*RSAPrivateKey)(priv), nil - case ECDSAP256SHA256, ECDSAP384SHA384: - var c elliptic.Curve - switch r.Algorithm { - case ECDSAP256SHA256: - c = elliptic.P256() - case ECDSAP384SHA384: - c = elliptic.P384() - } - priv, err := ecdsa.GenerateKey(c, rand.Reader) - if err != nil { - return nil, err - } - r.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y) - return (*ECDSAPrivateKey)(priv), nil - default: - return nil, ErrAlg - } -} - -// PrivateKeyString converts a PrivateKey to a string. This string has the same -// format as the private-key-file of BIND9 (Private-key-format: v1.3). -// It needs some info from the key (the algorithm), so its a method of the -// DNSKEY and calls PrivateKey.String(alg). -func (r *DNSKEY) PrivateKeyString(p PrivateKey) string { - return p.String(r.Algorithm) -} - -type RSAPrivateKey rsa.PrivateKey - -func (p *RSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) { - var hash crypto.Hash - switch alg { - case RSASHA1, RSASHA1NSEC3SHA1: - hash = crypto.SHA1 - case RSASHA256: - hash = crypto.SHA256 - case RSASHA512: - hash = crypto.SHA512 - default: - return nil, ErrAlg - } - return rsa.SignPKCS1v15(nil, (*rsa.PrivateKey)(p), hash, hashed) -} - -func (p *RSAPrivateKey) String(alg uint8) string { - if true { - algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")" - modulus := toBase64(p.PublicKey.N.Bytes()) - e := big.NewInt(int64(p.PublicKey.E)) - publicExponent := toBase64(e.Bytes()) - privateExponent := toBase64(p.D.Bytes()) - prime1 := toBase64(p.Primes[0].Bytes()) - prime2 := toBase64(p.Primes[1].Bytes()) - // Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm - // and from: http://code.google.com/p/go/issues/detail?id=987 - one := big.NewInt(1) - p_1 := big.NewInt(0).Sub(p.Primes[0], one) - q_1 := big.NewInt(0).Sub(p.Primes[1], one) - exp1 := big.NewInt(0).Mod(p.D, p_1) - exp2 := big.NewInt(0).Mod(p.D, q_1) - coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0]) - - exponent1 := toBase64(exp1.Bytes()) - exponent2 := toBase64(exp2.Bytes()) - coefficient := toBase64(coeff.Bytes()) - - return _FORMAT + - "Algorithm: " + algorithm + "\n" + - "Modulus: " + modulus + "\n" + - "PublicExponent: " + publicExponent + "\n" + - "PrivateExponent: " + privateExponent + "\n" + - "Prime1: " + prime1 + "\n" + - "Prime2: " + prime2 + "\n" + - "Exponent1: " + exponent1 + "\n" + - "Exponent2: " + exponent2 + "\n" + - "Coefficient: " + coefficient + "\n" - } -} - -type ECDSAPrivateKey ecdsa.PrivateKey - -func (p *ECDSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) { - var intlen int - switch alg { - case ECDSAP256SHA256: - intlen = 32 - case ECDSAP384SHA384: - intlen = 48 - default: - return nil, ErrAlg - } - r1, s1, err := ecdsa.Sign(rand.Reader, (*ecdsa.PrivateKey)(p), hashed) - if err != nil { - return nil, err - } - signature := intToBytes(r1, intlen) - signature = append(signature, intToBytes(s1, intlen)...) - return signature, nil -} - -func (p *ECDSAPrivateKey) String(alg uint8) string { - if true { - algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")" - var intlen int - switch alg { - case ECDSAP256SHA256: - intlen = 32 - case ECDSAP384SHA384: - intlen = 48 - } - private := toBase64(intToBytes(p.D, intlen)) - return _FORMAT + - "Algorithm: " + algorithm + "\n" + - "PrivateKey: " + private + "\n" - } -} - -type DSAPrivateKey dsa.PrivateKey - -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 -} - -func (p *DSAPrivateKey) String(alg uint8) string { - if true { - algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")" - T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8) - prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8)) - subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20)) - base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8)) - priv := toBase64(intToBytes(p.X, 20)) - pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8)) - return _FORMAT + - "Algorithm: " + algorithm + "\n" + - "Prime(p): " + prime + "\n" + - "Subprime(q): " + subprime + "\n" + - "Base(g): " + base + "\n" + - "Private_value(x): " + priv + "\n" + - "Public_value(y): " + pub + "\n" - } -}