From: nsz Date: Mon, 12 Dec 2011 14:31:39 +0000 (+0100) Subject: key cleanup X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=203da80978a9c2924d02c039298ee80bafda14ff;p=epoint key cleanup --- diff --git a/pkg/key/key.go b/pkg/key/key.go index 67fac98..37f2c63 100644 --- a/pkg/key/key.go +++ b/pkg/key/key.go @@ -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 } diff --git a/pkg/key/key_test.go b/pkg/key/key_test.go index cfe912c..1e594fe 100644 --- a/pkg/key/key_test.go +++ b/pkg/key/key_test.go @@ -24,24 +24,24 @@ func testSignAndVerify(t *testing.T, priv *openpgp.Entity) { } func TestKey(t *testing.T) { - key, err := GenKey() + key, err := RandomDsaKey() if err != nil { t.Errorf("gen dsa key failed: %s", err) return } - priv, err := NewEntity(key, time.Seconds(), "a", "b", "c") + priv, err := New(key, time.Seconds(), "a", "b", "c") if err != nil { - t.Errorf("new entity failed: %s", err) + t.Errorf("New failed: %s", err) } else { testSignAndVerify(t, priv) } } -func TestGenIssuer(t *testing.T) { +func TestIssuerHolder(t *testing.T) { denomination := "1/100 EUR" - priv, err := NewIssuerEntity([]byte("issuer-rand"), denomination) + priv, err := Issuer([]byte("issuer-rand"), denomination) if err != nil { - t.Errorf("new entity failed: %s", err) + t.Errorf("Issuer failed: %s", err) } else { testSignAndVerify(t, priv) } @@ -62,9 +62,9 @@ func TestGenIssuer(t *testing.T) { t.Errorf("pub key parsing failed: %s", err) return } - isIssuer, issuer, denom, err := CheckEntity(es[0]) + isIssuer, issuer, denom, err := Check(es[0]) if err != nil { - t.Errorf("pub key parsing failed: %s", err) + t.Errorf("Check failed: %s", err) return } if !isIssuer { @@ -78,9 +78,9 @@ func TestGenIssuer(t *testing.T) { t.Errorf("expected denomination %q got %q", denomination, denom) } - priv, err = NewHolderEntity([]byte("holder-rand"), issuerfpr, denomination) + priv, err = Holder([]byte("holder-rand"), issuerfpr, denomination) if err != nil { - t.Errorf("new entity failed: %s", err) + t.Errorf("Holder failed: %s", err) } else { testSignAndVerify(t, priv) } @@ -101,9 +101,9 @@ func TestGenIssuer(t *testing.T) { t.Errorf("pub key parsing failed: %s", err) return } - isIssuer, issuer, denom, err = CheckEntity(es[0]) + isIssuer, issuer, denom, err = Check(es[0]) if err != nil { - t.Errorf("pub key parsing failed: %s", err) + t.Errorf("Check failed: %s", err) return } if isIssuer {