Go - Golang openpg - Create Key pair and create signature

匿名 (未验证) 提交于 2019-12-03 08:52:47

问题:

I'm currently working on openpgp in combination with golang. I use the following code to generate a new keypair and create a self-signature on the resulting public key:

package main  import (     "bytes"     "crypto"     "time"     "golang.org/x/crypto/openpgp"     "golang.org/x/crypto/openpgp/armor"     "golang.org/x/crypto/openpgp/packet"     "fmt" )  //Create ASscii Armor from openpgp.Entity func PubEntToAsciiArmor(pubEnt *openpgp.Entity) (asciiEntity string) {     gotWriter := bytes.NewBuffer(nil)     wr, errEncode := armor.Encode(gotWriter, openpgp.PublicKeyType, nil)     if errEncode != nil {         fmt.Println("Encoding Armor ", errEncode.Error())         return     }     errSerial := pubEnt.Serialize(wr)     if errSerial != nil {         fmt.Println("Serializing PubKey ", errSerial.Error())     }     errClosing := wr.Close()     if errClosing != nil {         fmt.Println("Closing writer ", errClosing.Error())     }     asciiEntity = gotWriter.String()     return }   func main() {      var entity *openpgp.Entity     entity, err := openpgp.NewEntity("itis", "test", "itis@itis3.com", nil)     if err != nil {         fmt.Println("ERROR")     }      usrIdstring := ""     for _, uIds := range entity.Identities {         usrIdstring = uIds.Name      }      var priKey = entity.PrivateKey     var sig = new(packet.Signature)         //Prepare sign with our configs/////IS IT A MUST ??     sig.Hash = crypto.SHA1     sig.PubKeyAlgo = priKey.PubKeyAlgo     sig.CreationTime = time.Now()     dur := new(uint32)     *dur = uint32(365 * 24 * 60 * 60)     sig.SigLifetimeSecs = dur //a year     issuerUint := new(uint64)     *issuerUint = priKey.KeyId     sig.IssuerKeyId = issuerUint     sig.SigType = packet.SigTypeGenericCert       err = sig.SignKey(entity.PrimaryKey, entity.PrivateKey, nil)     if err != nil {         fmt.Println("ERROR")     }     err = sig.SignUserId(usrIdstring, entity.PrimaryKey, entity.PrivateKey, nil)     if err != nil {         fmt.Println("ERROR")     }      entity.SignIdentity(usrIdstring, entity, nil)      var copy = entity     var asciiSignedKey = PubEntToAsciiArmor(copy)     fmt.Println(asciiSignedKey) }

1.) When I serialize the public key (to get an armored version of it), I get the following error message:

Serializing PubKey openpgp: invalid argument: Signature: need to call Sign, SignUserId or SignKey before Serialize

I thought I just used every possible way to create a signature on that key?

2.) I still receive an output from problem 1, when I upload the key to a keyserver, than the available information are incomplete. Only the key-id and the creation date are listed. All additional information like, self-signature, user-id-string and so on are missing (example: https://pgp.mit.edu/pks/lookup?search=0xbe6ee21e94a73ba5&op=index). What went wrong? Is it related to error 1?

PS: I am new to golang, started today.

回答1:

Maybe this will do what you want. Disclaimer: I am not an expert in openpgp; I don't know whether this is correct or not. But it does work with gpg --import.

package main  import (         "fmt"         "os"          "golang.org/x/crypto/openpgp"         "golang.org/x/crypto/openpgp/armor" )  func main() {         var e *openpgp.Entity         e, err := openpgp.NewEntity("itis", "test", "itis@itis3.com", nil)         if err != nil {                 fmt.Println(err)                 return         }          // Add more identities here if you wish          // Sign all the identities         for _, id := range e.Identities {                 err := id.SelfSignature.SignUserId(id.UserId.Id, e.PrimaryKey, e.PrivateKey, nil)                 if err != nil {                         fmt.Println(err)                         return                 }         }          w, err := armor.Encode(os.Stdout, openpgp.PublicKeyType, nil)         if err != nil {                 fmt.Println(err)                 return         }         defer w.Close()          e.Serialize(w) }


回答2:

This seems to be a known issue: https://github.com/golang/go/issues/6483. The workaround is to call SerializePrivate first, even if you don't use the result.



回答3:

I wrote https://github.com/alokmenghrajani/gpgeez for exactly this purpose. It's a Go library which makes things like key creating or exporting a key as an armored string easier.

Here is the gist of it, without any error checking:

func CreateKey() *openpgp.Entity {   key, _ := openpgp.NewEntity(name, comment, email, nil)    for _, id := range key.Identities {     id.SelfSignature.PreferredSymmetric = []uint8{...}         id.SelfSignature.PreferredHash = []uint8{...}         id.SelfSignature.PreferredCompression = []uint8{...}      id.SelfSignature.SignUserId(id.UserId.Id, key.PrimaryKey, key.PrivateKey, nil)   }    // Self-sign the Subkeys   for _, subkey := range key.Subkeys {     subkey.Sig.SignKey(subkey.PublicKey, key.PrivateKey, nil)   }    return r }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!