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)
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")
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
}
}
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)
}
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 {
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)
}
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 {