7 "crypto/openpgp/packet"
15 const P = "C1773C0DEF5C1D75BA556137CBCE0F6EE534034FCE503D7ED1FF7A27E8638EAC3BD627C734E08D1D828B52C39EB602DC63D9544D1734A981AE2408F8037305B548EFE457E2A79EB511CFF11A0C3DB05CF64971A6AF3EF191D3EBA0841AAAC3BECF4B6CF199EDD59C732BA642A0074BAE1DC3CF724F830930C898B1865F597EF7"
16 const Q = "DCA9E7C9FDC18CB0B8E9A80E487F96438147EF75"
17 const G = "502FF28CC4D7BC1100123C9227994341C29773BFBD8D7E8FFED6D87A9D82FE573744AC8E4CCAE93E3A017A6388921CA5B0C9349B249EF87AB30AE01B3C9FD723001CB25E560CA6C25EDFC97613B41346D0597C2ECA2BED7BC6C9A032049B3FFF9AED462D09651A5995DB8E5E111384AC7B62CBAD827009269FC79D3E4E6D8AA3"
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)
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
36 x.Sub(priv.Q, big.NewInt(1))
38 switch x.Cmp(priv.Q) {
40 x.Sub(priv.Q, big.NewInt(2))
46 priv.Y.Exp(priv.G, x, priv.P)
50 func GenKey() (priv *dsa.PrivateKey, err error) {
51 x := make([]byte, len(Q)/2)
52 _, err = io.ReadFull(rand.Reader, x)
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)
63 return nil, fmt.Errorf("NewEntity: invalid argument: user id field contained invalid characters")
65 t := uint32(currentTimeSecs)
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),
72 e.Identities[uid.Id] = &openpgp.Identity{
75 SelfSignature: &packet.Signature{
77 SigType: packet.SigTypePositiveCert,
78 PubKeyAlgo: packet.PubKeyAlgoDSA,
80 IsPrimaryId: &isPrimaryId,
84 IssuerKeyId: &e.PrimaryKey.KeyId,
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{
94 SigType: packet.SigTypeSubkeyBinding,
95 PubKeyAlgo: packet.PubKeyAlgoRSA,
98 FlagEncryptStorage: true,
99 FlagEncryptCommunications: true,
100 IssuerKeyId: &e.PrimaryKey.KeyId,
107 // simple key generation for obligation issuer clients
108 func NewIssuerEntity(r []byte, denomination string) (e *openpgp.Entity, err error) {
109 return NewEntity(PrivKey(r), 0, "Issuer", denomination, "")
111 // simple key generation for obligation holder clients
112 func NewHolderEntity(r []byte, issuer, denomination string) (e *openpgp.Entity, err error) {
113 return NewEntity(PrivKey(r), 0, "Holder of " + issuer, denomination, "")
116 // check the issuer and denomination associated with the given pgp key
117 func CheckEntity(e *openpgp.Entity) (isIssuer bool, issuer, denomination string, err error) {
118 // TODO: allow non-epoint uids
119 if len(e.Identities) != 1 {
120 err = fmt.Errorf("CheckEntity: expected one identity")
123 for _, i := range e.Identities {
124 denomination = i.UserId.Comment
125 if i.UserId.Name == "Issuer" {
127 issuer = fmt.Sprintf("%X", e.PrimaryKey.Fingerprint)
130 prefix := "Holder of "
131 if i.UserId.Name[:len(prefix)] == prefix {
132 issuer = i.UserId.Name[len(prefix):]
137 err = fmt.Errorf("CheckENtity: invalid userid")