|
|
|
@ -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)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|