add simple dsa key generator
authornsz <nsz@port70.net>
Tue, 29 Nov 2011 16:20:11 +0000 (17:20 +0100)
committernsz <nsz@port70.net>
Tue, 29 Nov 2011 16:20:11 +0000 (17:20 +0100)
cmd/genkey/Makefile [new file with mode: 0644]
cmd/genkey/genkey.go [new file with mode: 0644]
dsakey/Makefile [new file with mode: 0644]
dsakey/dsakey.go [new file with mode: 0644]
dsakey/dsakey_test.go [new file with mode: 0644]

diff --git a/cmd/genkey/Makefile b/cmd/genkey/Makefile
new file mode 100644 (file)
index 0000000..4af0d05
--- /dev/null
@@ -0,0 +1,7 @@
+include $(GOROOT)/src/Make.inc
+
+TARG=genkey
+GOFILES=\
+       genkey.go
+
+include $(GOROOT)/src/Make.cmd
diff --git a/cmd/genkey/genkey.go b/cmd/genkey/genkey.go
new file mode 100644 (file)
index 0000000..6420306
--- /dev/null
@@ -0,0 +1,81 @@
+package main
+
+import (
+       "epoint/dsakey"
+       "crypto/openpgp"
+       "log"
+       "os"
+       "time"
+)
+
+const usage = "usage: ./genkey name comment email seckeyfile pubkeyfile < seed"
+
+func serialize(e *openpgp.Entity, sk, pk string) (err error) {
+       f, err := os.Create(sk)
+       if err != nil {
+               return
+       }
+       err = e.SerializePrivate(f)
+       if err != nil {
+               return
+       }
+       err = f.Sync()
+       if err != nil {
+               return
+       }
+       err = f.Close()
+       if err != nil {
+               return
+       }
+       // public key
+       f, err = os.Create(pk)
+       if err != nil {
+               return
+       }
+       /*
+               // TODO: maybe Serialize should do this internally
+               for _, ident := range e.Identities {
+                       err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey)
+                       if err != nil {
+                               return
+                       }
+               }
+               for _, subkey := range e.Subkeys {
+                       err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey)
+                       if err != nil {
+                               return
+                       }
+               }
+       */
+       err = e.Serialize(f)
+       if err != nil {
+               return
+       }
+       err = f.Sync()
+       if err != nil {
+               return
+       }
+       err = f.Close()
+       return
+}
+
+func main() {
+       if len(os.Args) != 6 {
+               log.Fatal(usage)
+       }
+       b := make([]byte, 1000)
+       n, err := os.Stdin.Read(b)
+       if err != nil {
+               log.Print(err)
+               log.Fatal(usage)
+       }
+       key := dsakey.PrivKey(b[:n])
+       e, err := dsakey.NewEntity(key, time.Seconds(), os.Args[1], os.Args[2], os.Args[3])
+       if err != nil {
+               log.Fatal(err)
+       }
+       err = serialize(e, os.Args[4], os.Args[5])
+       if err != nil {
+               log.Fatal(err)
+       }
+}
diff --git a/dsakey/Makefile b/dsakey/Makefile
new file mode 100644 (file)
index 0000000..bd29402
--- /dev/null
@@ -0,0 +1,6 @@
+include $(GOROOT)/src/Make.inc
+
+TARG=epoint/dsakey
+GOFILES=dsakey.go
+
+include $(GOROOT)/src/Make.pkg
diff --git a/dsakey/dsakey.go b/dsakey/dsakey.go
new file mode 100644 (file)
index 0000000..eb5d129
--- /dev/null
@@ -0,0 +1,106 @@
+package dsakey
+
+import (
+       "crypto/sha1"
+       "crypto/dsa"
+       "crypto/openpgp"
+       "crypto/openpgp/packet"
+       "crypto/rand"
+       "crypto"
+       "fmt"
+       "io"
+       "math/big"
+)
+
+const P = "C1773C0DEF5C1D75BA556137CBCE0F6EE534034FCE503D7ED1FF7A27E8638EAC3BD627C734E08D1D828B52C39EB602DC63D9544D1734A981AE2408F8037305B548EFE457E2A79EB511CFF11A0C3DB05CF64971A6AF3EF191D3EBA0841AAAC3BECF4B6CF199EDD59C732BA642A0074BAE1DC3CF724F830930C898B1865F597EF7"
+const Q = "DCA9E7C9FDC18CB0B8E9A80E487F96438147EF75"
+const G = "502FF28CC4D7BC1100123C9227994341C29773BFBD8D7E8FFED6D87A9D82FE573744AC8E4CCAE93E3A017A6388921CA5B0C9349B249EF87AB30AE01B3C9FD723001CB25E560CA6C25EDFC97613B41346D0597C2ECA2BED7BC6C9A032049B3FFF9AED462D09651A5995DB8E5E111384AC7B62CBAD827009269FC79D3E4E6D8AA3"
+
+func PrivKey(r []byte) *dsa.PrivateKey {
+       priv := new(dsa.PrivateKey)
+       priv.Parameters.P,_ = new(big.Int).SetString(P, 16)
+       priv.Parameters.Q,_ = new(big.Int).SetString(Q, 16)
+       priv.Parameters.G,_ = new(big.Int).SetString(G, 16)
+
+       // q > 2^159 prime
+       // x = sha1(r)
+       // if x == 0 then x = q - 1
+       // if x == q then x = q - 2
+       // if x > q  then x = x mod q
+
+       x := new(big.Int)
+       h := sha1.New()
+       h.Write(r)
+       x.SetBytes(h.Sum())
+       if x.Sign() == 0 {
+               x.Sub(priv.Q, big.NewInt(1))
+       }
+       switch x.Cmp(priv.Q) {
+       case 0:
+               x.Sub(priv.Q, big.NewInt(2))
+       case 1:
+               x.Sub(x, priv.Q)
+       }
+       priv.X = x
+       priv.Y = new(big.Int)
+       priv.Y.Exp(priv.G, x, priv.P)
+       return priv
+}
+
+func GenKey() (priv *dsa.PrivateKey, err error) {
+       x := make([]byte, len(Q)/2)
+       _, err = io.ReadFull(rand.Reader, x)
+       priv = PrivKey(x)
+       return
+}
+
+// NewEntity returns an Entity that contains a fresh DSA private key with a
+// single identity composed of the given full name, comment and email, any of
+// which may be empty but must not contain any of "()<>\x00".
+func NewEntity(priv *dsa.PrivateKey, currentTimeSecs int64, name, comment, email string) (e *openpgp.Entity, err error) {
+       uid := packet.NewUserId(name, comment, email)
+       if uid == nil {
+               return nil, fmt.Errorf("NewEntity: invalid argument: user id field contained invalid characters")
+       }
+       t := uint32(currentTimeSecs)
+       e = &openpgp.Entity{
+               PrimaryKey: packet.NewDSAPublicKey(t, &priv.PublicKey, false /* not a subkey */ ),
+               PrivateKey: packet.NewDSAPrivateKey(t, priv, false /* not a subkey */ ),
+               Identities: make(map[string]*openpgp.Identity),
+       }
+       isPrimaryId := true
+       e.Identities[uid.Id] = &openpgp.Identity{
+               Name:   uid.Name,
+               UserId: uid,
+               SelfSignature: &packet.Signature{
+                       CreationTime: t,
+                       SigType:      packet.SigTypePositiveCert,
+                       PubKeyAlgo:   packet.PubKeyAlgoDSA,
+                       Hash:         crypto.SHA256,
+                       IsPrimaryId:  &isPrimaryId,
+                       FlagsValid:   true,
+                       FlagSign:     true,
+                       FlagCertify:  true,
+                       IssuerKeyId:  &e.PrimaryKey.KeyId,
+               },
+       }
+/*
+       e.Subkeys = make([]Subkey, 1)
+       e.Subkeys[0] = Subkey{
+               PublicKey:  packet.NewRSAPublicKey(t, &encryptingPriv.PublicKey, true),
+               PrivateKey: packet.NewRSAPrivateKey(t, encryptingPriv, true),
+               Sig: &packet.Signature{
+                       CreationTime:              t,
+                       SigType:                   packet.SigTypeSubkeyBinding,
+                       PubKeyAlgo:                packet.PubKeyAlgoRSA,
+                       Hash:                      crypto.SHA256,
+                       FlagsValid:                true,
+                       FlagEncryptStorage:        true,
+                       FlagEncryptCommunications: true,
+                       IssuerKeyId:               &e.PrimaryKey.KeyId,
+               },
+       }
+*/
+       return
+}
+
diff --git a/dsakey/dsakey_test.go b/dsakey/dsakey_test.go
new file mode 100644 (file)
index 0000000..9245199
--- /dev/null
@@ -0,0 +1,38 @@
+package dsakey
+
+import (
+       "crypto/openpgp"
+//     "fmt"
+       "bytes"
+       "time"
+       "testing"
+)
+
+func testSignAndVerify(t *testing.T, priv *openpgp.Entity) {
+       msg := []byte("testing")
+       w := new(bytes.Buffer)
+       err := openpgp.DetachSign(w, priv, bytes.NewBuffer(msg))
+       if err != nil {
+               t.Errorf("error signing: %s", err)
+               return
+       }
+
+       _, err = openpgp.CheckDetachedSignature(openpgp.EntityList{priv}, bytes.NewBuffer(msg), w)
+       if err != nil {
+               t.Errorf("Verify failed")
+       }
+}
+
+func TestKey(t *testing.T) {
+       key, err := GenKey()
+       if err != nil {
+               t.Errorf("gen dsa key failed: %s", err)
+               return
+       }
+       priv, err := NewEntity(key, time.Seconds(), "a", "b", "c")
+       if err != nil {
+               t.Errorf("new entity failed: %s", err)
+       } else {
+               testSignAndVerify(t, priv)
+       }
+}