+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
+}
+