|
|
|
@ -43,6 +43,12 @@ type GPGKey struct { |
|
|
|
|
CanCertify bool |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//GPGKeyImport the original import of key
|
|
|
|
|
type GPGKeyImport struct { |
|
|
|
|
KeyID string `xorm:"pk CHAR(16) NOT NULL"` |
|
|
|
|
Content string `xorm:"TEXT NOT NULL"` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// BeforeInsert will be invoked by XORM before inserting a record
|
|
|
|
|
func (key *GPGKey) BeforeInsert() { |
|
|
|
|
key.AddedUnix = util.TimeStampNow() |
|
|
|
@ -74,6 +80,18 @@ func GetGPGKeyByID(keyID int64) (*GPGKey, error) { |
|
|
|
|
return key, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GetGPGImportByKeyID returns the import public armored key by given KeyID.
|
|
|
|
|
func GetGPGImportByKeyID(keyID string) (*GPGKeyImport, error) { |
|
|
|
|
key := new(GPGKeyImport) |
|
|
|
|
has, err := x.ID(keyID).Get(key) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} else if !has { |
|
|
|
|
return nil, ErrGPGKeyImportNotExist{keyID} |
|
|
|
|
} |
|
|
|
|
return key, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// checkArmoredGPGKeyString checks if the given key string is a valid GPG armored key.
|
|
|
|
|
// The function returns the actual public key on success
|
|
|
|
|
func checkArmoredGPGKeyString(content string) (*openpgp.Entity, error) { |
|
|
|
@ -84,15 +102,37 @@ func checkArmoredGPGKeyString(content string) (*openpgp.Entity, error) { |
|
|
|
|
return list[0], nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//addGPGKey add key and subkeys to database
|
|
|
|
|
func addGPGKey(e Engine, key *GPGKey) (err error) { |
|
|
|
|
//addGPGKey add key, import and subkeys to database
|
|
|
|
|
func addGPGKey(e Engine, key *GPGKey, content string) (err error) { |
|
|
|
|
//Add GPGKeyImport
|
|
|
|
|
if _, err = e.Insert(GPGKeyImport{ |
|
|
|
|
KeyID: key.KeyID, |
|
|
|
|
Content: content, |
|
|
|
|
}); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
// Save GPG primary key.
|
|
|
|
|
if _, err = e.Insert(key); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
// Save GPG subs key.
|
|
|
|
|
for _, subkey := range key.SubsKey { |
|
|
|
|
if err := addGPGSubKey(e, subkey); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//addGPGSubKey add subkeys to database
|
|
|
|
|
func addGPGSubKey(e Engine, key *GPGKey) (err error) { |
|
|
|
|
// Save GPG primary key.
|
|
|
|
|
if _, err = e.Insert(key); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
// Save GPG subs key.
|
|
|
|
|
for _, subkey := range key.SubsKey { |
|
|
|
|
if err := addGPGKey(e, subkey); err != nil { |
|
|
|
|
if err := addGPGSubKey(e, subkey); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -127,14 +167,14 @@ func AddGPGKey(ownerID int64, content string) (*GPGKey, error) { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if err = addGPGKey(sess, key); err != nil { |
|
|
|
|
if err = addGPGKey(sess, key, content); err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return key, sess.Commit() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//base64EncPubKey encode public kay content to base 64
|
|
|
|
|
//base64EncPubKey encode public key content to base 64
|
|
|
|
|
func base64EncPubKey(pubkey *packet.PublicKey) (string, error) { |
|
|
|
|
var w bytes.Buffer |
|
|
|
|
err := pubkey.Serialize(&w) |
|
|
|
@ -144,6 +184,34 @@ func base64EncPubKey(pubkey *packet.PublicKey) (string, error) { |
|
|
|
|
return base64.StdEncoding.EncodeToString(w.Bytes()), nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//base64DecPubKey decode public key content from base 64
|
|
|
|
|
func base64DecPubKey(content string) (*packet.PublicKey, error) { |
|
|
|
|
b, err := readerFromBase64(content) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
//Read key
|
|
|
|
|
p, err := packet.Read(b) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
//Check type
|
|
|
|
|
pkey, ok := p.(*packet.PublicKey) |
|
|
|
|
if !ok { |
|
|
|
|
return nil, fmt.Errorf("key is not a public key") |
|
|
|
|
} |
|
|
|
|
return pkey, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//GPGKeyToEntity retrieve the imported key and the traducted entity
|
|
|
|
|
func GPGKeyToEntity(k *GPGKey) (*openpgp.Entity, error) { |
|
|
|
|
impKey, err := GetGPGImportByKeyID(k.KeyID) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
return checkArmoredGPGKeyString(impKey.Content) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//parseSubGPGKey parse a sub Key
|
|
|
|
|
func parseSubGPGKey(ownerID int64, primaryID string, pubkey *packet.PublicKey, expiry time.Time) (*GPGKey, error) { |
|
|
|
|
content, err := base64EncPubKey(pubkey) |
|
|
|
@ -244,6 +312,11 @@ func deleteGPGKey(e *xorm.Session, keyID string) (int64, error) { |
|
|
|
|
if keyID == "" { |
|
|
|
|
return 0, fmt.Errorf("empty KeyId forbidden") //Should never happen but just to be sure
|
|
|
|
|
} |
|
|
|
|
//Delete imported key
|
|
|
|
|
n, err := e.Where("key_id=?", keyID).Delete(new(GPGKeyImport)) |
|
|
|
|
if err != nil { |
|
|
|
|
return n, err |
|
|
|
|
} |
|
|
|
|
return e.Where("key_id=?", keyID).Or("primary_key_id=?", keyID).Delete(new(GPGKey)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -339,22 +412,10 @@ func verifySign(s *packet.Signature, h hash.Hash, k *GPGKey) error { |
|
|
|
|
return fmt.Errorf("key can not sign") |
|
|
|
|
} |
|
|
|
|
//Decode key
|
|
|
|
|
b, err := readerFromBase64(k.Content) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
//Read key
|
|
|
|
|
p, err := packet.Read(b) |
|
|
|
|
pkey, err := base64DecPubKey(k.Content) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//Check type
|
|
|
|
|
pkey, ok := p.(*packet.PublicKey) |
|
|
|
|
if !ok { |
|
|
|
|
return fmt.Errorf("key is not a public key") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return pkey.VerifySignature(h, s) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|