key cleanup
[epoint] / pkg / key / key.go
index 67fac98..37f2c63 100644 (file)
@@ -34,22 +34,23 @@ const P = "A4D2B9575C25F0E622B8694387128A793E1AD27D12FFF4B5BA11A37CEFD31C935BCBB
 const Q = "FFFFFFFFFFFFFFFFFFFF254EAF9E7916D607AAAF"
 const G = "7EA5C898777BE4BB29DCDC47289E718F7274C9CD7E570D3D552F3B3EE43C3DEF7BA68E57786926520CCAC71DBA13F37C4064395D5AF3334A04ABD8CED5E7FF476C661953936E8ADDE96A39D8C4AC1080A2BE3FE863A24B08BD43827E54AFADA72433704EA3C12E50E5BD08C130C68A1402FC20DA79CFE0DE931C414348D32B10"
 
-func PrivKey(r []byte) *dsa.PrivateKey {
+// Calculate DSA private key from given random seed r
+func DsaKey(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)
 
        x := new(big.Int)
-       for {
-               h := sha1.New()
-               h.Write(r)
-               r = h.Sum()
-               x.SetBytes(r)
-               if x.Sign() == 1 && x.Cmp(priv.Q) < 0 {
-                       break
-               }
-               // rarely reachable
+loop:
+       h := sha1.New()
+       h.Write(r)
+       r = h.Sum()
+       x.SetBytes(r)
+       // TODO: zero out r and h ?
+       if x.Sign() == 0 || x.Cmp(priv.Q) >= 0 {
+               // very rare
+               goto loop
        }
        priv.X = x
        priv.Y = new(big.Int)
@@ -57,17 +58,18 @@ func PrivKey(r []byte) *dsa.PrivateKey {
        return priv
 }
 
-func GenKey() (priv *dsa.PrivateKey, err error) {
-       x := make([]byte, len(Q)/2)
-       _, err = io.ReadFull(rand.Reader, x)
-       priv = PrivKey(x)
+// Generate a random DSA private key
+func RandomDsaKey() (priv *dsa.PrivateKey, err error) {
+       r := make([]byte, sha1.Size)
+       _, err = io.ReadFull(rand.Reader, r)
+       priv = DsaKey(r)
        return
 }
 
-// NewEntity returns an Entity that contains a fresh DSA private key with a
+// New returns an openpgp.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) {
+func New(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")
@@ -94,56 +96,34 @@ func NewEntity(priv *dsa.PrivateKey, currentTimeSecs int64, name, comment, email
                        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
 }
 
-// simple key generation for obligation issuer clients
-func NewIssuerEntity(r []byte, denomination string) (e *openpgp.Entity, err error) {
-       return NewEntity(PrivKey(r), 0, "Issuer", denomination, "")
+// Issuer generates a key for obligation issuer clients from random seed r
+func Issuer(r []byte, denomination string) (e *openpgp.Entity, err error) {
+       return New(DsaKey(r), 0, "Issuer", denomination, "")
 }
-// simple key generation for obligation holder clients
-func NewHolderEntity(r []byte, issuer, denomination string) (e *openpgp.Entity, err error) {
-       return NewEntity(PrivKey(r), 0, "Holder of "+issuer, denomination, "")
+// Holder generates a key for obligation holder clients from random seed r
+func Holder(r []byte, issuer, denomination string) (e *openpgp.Entity, err error) {
+       return New(DsaKey(r), 0, "Holder of "+issuer, denomination, "")
 }
 
-// check the issuer and denomination associated with the given pgp key
-func CheckEntity(e *openpgp.Entity) (isIssuer bool, issuer, denomination string, err error) {
-       // TODO: allow non-epoint uids
-       if len(e.Identities) != 1 {
-               err = fmt.Errorf("CheckEntity: expected one identity")
-               return
-       }
-       for _, i := range e.Identities {
-               denomination = i.UserId.Comment
-               if i.UserId.Name == "Issuer" {
+// Check the issuer and denomination associated with the given pgp key
+func Check(e *openpgp.Entity) (isIssuer bool, issuer, denomination string, err error) {
+       // allow multiple identities, use the first one that looks like an epoint uid
+       for _, id := range e.Identities {
+               denomination = id.UserId.Comment
+               if id.UserId.Name == "Issuer" {
                        isIssuer = true
                        issuer = fmt.Sprintf("%X", e.PrimaryKey.Fingerprint)
                        return
                }
-               prefix := "Holder of "
-               if i.UserId.Name[:len(prefix)] == prefix {
-                       issuer = i.UserId.Name[len(prefix):]
+               const prefix = "Holder of "
+               if id.UserId.Name[:len(prefix)] == prefix {
+                       issuer = id.UserId.Name[len(prefix):]
                        return
                }
-               break
        }
-       err = fmt.Errorf("CheckENtity: invalid userid")
+       err = fmt.Errorf("Check: no valid userid was found")
        return
 }