Go - Golang openpg - 创建密钥对并创建签名

时间:2015-04-28 20:55:17

标签: go gnupg pgp openpgp

我目前正在使用openpgp和golang一起工作。我使用以下代码生成新的密钥对,并在生成的公钥上创建自签名:

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。)当我序列化公钥(获取它的装甲版本)时,我收到以下错误消息:

  

序列化PubKey openpgp:无效参数:签名:需要在Serialize之前调用Sign,SignUserId或SignKey

我以为我只是用一切可能的方法在那个密钥上创建签名?

2。)当我将密钥上传到密钥服务器时,我仍然收到问题1的输出,而不是可用信息不完整。仅列出key-id和创建日期。缺少所有其他信息,如自签名,用户ID字符串等(例如:https://pgp.mit.edu/pks/lookup?search=0xbe6ee21e94a73ba5&op=index)。什么地方出了错?它与错误1有关吗?

PS:我是golang的新手,今天就开始了。

3 个答案:

答案 0 :(得分:3)

也许这会做你想要的。免责声明:我不是openpgp的专家;我不知道这是否正确。但它确实适用于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)
}

答案 1 :(得分:3)

我正是为了这个目的写了https://github.com/alokmenghrajani/gpgeez。它是一个Go库,可以更轻松地创建密钥或将密钥作为装甲字符串导出。

以下是它的要点,没有任何错误检查:

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
}

答案 2 :(得分:2)

这似乎是一个众所周知的问题:https://github.com/golang/go/issues/6483。解决方法是首先调用SerializePrivate,即使您不使用结果。