add simple dsa key generator
[epoint] / dsakey / dsakey.go
1 package dsakey
2
3 import (
4         "crypto/sha1"
5         "crypto/dsa"
6         "crypto/openpgp"
7         "crypto/openpgp/packet"
8         "crypto/rand"
9         "crypto"
10         "fmt"
11         "io"
12         "math/big"
13 )
14
15 const P = "C1773C0DEF5C1D75BA556137CBCE0F6EE534034FCE503D7ED1FF7A27E8638EAC3BD627C734E08D1D828B52C39EB602DC63D9544D1734A981AE2408F8037305B548EFE457E2A79EB511CFF11A0C3DB05CF64971A6AF3EF191D3EBA0841AAAC3BECF4B6CF199EDD59C732BA642A0074BAE1DC3CF724F830930C898B1865F597EF7"
16 const Q = "DCA9E7C9FDC18CB0B8E9A80E487F96438147EF75"
17 const G = "502FF28CC4D7BC1100123C9227994341C29773BFBD8D7E8FFED6D87A9D82FE573744AC8E4CCAE93E3A017A6388921CA5B0C9349B249EF87AB30AE01B3C9FD723001CB25E560CA6C25EDFC97613B41346D0597C2ECA2BED7BC6C9A032049B3FFF9AED462D09651A5995DB8E5E111384AC7B62CBAD827009269FC79D3E4E6D8AA3"
18
19 func PrivKey(r []byte) *dsa.PrivateKey {
20         priv := new(dsa.PrivateKey)
21         priv.Parameters.P,_ = new(big.Int).SetString(P, 16)
22         priv.Parameters.Q,_ = new(big.Int).SetString(Q, 16)
23         priv.Parameters.G,_ = new(big.Int).SetString(G, 16)
24
25         // q > 2^159 prime
26         // x = sha1(r)
27         // if x == 0 then x = q - 1
28         // if x == q then x = q - 2
29         // if x > q  then x = x mod q
30
31         x := new(big.Int)
32         h := sha1.New()
33         h.Write(r)
34         x.SetBytes(h.Sum())
35         if x.Sign() == 0 {
36                 x.Sub(priv.Q, big.NewInt(1))
37         }
38         switch x.Cmp(priv.Q) {
39         case 0:
40                 x.Sub(priv.Q, big.NewInt(2))
41         case 1:
42                 x.Sub(x, priv.Q)
43         }
44         priv.X = x
45         priv.Y = new(big.Int)
46         priv.Y.Exp(priv.G, x, priv.P)
47         return priv
48 }
49
50 func GenKey() (priv *dsa.PrivateKey, err error) {
51         x := make([]byte, len(Q)/2)
52         _, err = io.ReadFull(rand.Reader, x)
53         priv = PrivKey(x)
54         return
55 }
56
57 // NewEntity returns an Entity that contains a fresh DSA private key with a
58 // single identity composed of the given full name, comment and email, any of
59 // which may be empty but must not contain any of "()<>\x00".
60 func NewEntity(priv *dsa.PrivateKey, currentTimeSecs int64, name, comment, email string) (e *openpgp.Entity, err error) {
61         uid := packet.NewUserId(name, comment, email)
62         if uid == nil {
63                 return nil, fmt.Errorf("NewEntity: invalid argument: user id field contained invalid characters")
64         }
65         t := uint32(currentTimeSecs)
66         e = &openpgp.Entity{
67                 PrimaryKey: packet.NewDSAPublicKey(t, &priv.PublicKey, false /* not a subkey */ ),
68                 PrivateKey: packet.NewDSAPrivateKey(t, priv, false /* not a subkey */ ),
69                 Identities: make(map[string]*openpgp.Identity),
70         }
71         isPrimaryId := true
72         e.Identities[uid.Id] = &openpgp.Identity{
73                 Name:   uid.Name,
74                 UserId: uid,
75                 SelfSignature: &packet.Signature{
76                         CreationTime: t,
77                         SigType:      packet.SigTypePositiveCert,
78                         PubKeyAlgo:   packet.PubKeyAlgoDSA,
79                         Hash:         crypto.SHA256,
80                         IsPrimaryId:  &isPrimaryId,
81                         FlagsValid:   true,
82                         FlagSign:     true,
83                         FlagCertify:  true,
84                         IssuerKeyId:  &e.PrimaryKey.KeyId,
85                 },
86         }
87 /*
88         e.Subkeys = make([]Subkey, 1)
89         e.Subkeys[0] = Subkey{
90                 PublicKey:  packet.NewRSAPublicKey(t, &encryptingPriv.PublicKey, true),
91                 PrivateKey: packet.NewRSAPrivateKey(t, encryptingPriv, true),
92                 Sig: &packet.Signature{
93                         CreationTime:              t,
94                         SigType:                   packet.SigTypeSubkeyBinding,
95                         PubKeyAlgo:                packet.PubKeyAlgoRSA,
96                         Hash:                      crypto.SHA256,
97                         FlagsValid:                true,
98                         FlagEncryptStorage:        true,
99                         FlagEncryptCommunications: true,
100                         IssuerKeyId:               &e.PrimaryKey.KeyId,
101                 },
102         }
103 */
104         return
105 }
106