douwei7501 2014-09-07 22:21
浏览 76
已采纳

openpgp golang gpg库的问题

So I'm pretty new to golang and i'm struggling to get a working example going of encrypting some text with openpgp and decrypting it again.

Here is what I have so far: (https://gist.github.com/93750a142d3de4e8fdd2.git)

package main

import (
    "log"
    "bytes"
    "code.google.com/p/go.crypto/openpgp"
    "encoding/base64"
    "io/ioutil"
    "os"
)

// create gpg keys with
// $ gpg --gen-key
// ensure you correct paths and passphrase

const mysecretstring = "this is so very secret!"
const secretKeyring = "/Users/stuart-warren/.gnupg/secring.gpg"
const publicKeyring = "/Users/stuart-warren/.gnupg/pubring.gpg"
const passphrase = "1234"

func main() {
    log.Printf("Secret: ", mysecretstring)
    log.Printf("Secret Keyring: ", secretKeyring)
    log.Printf("Public Keyring: ", publicKeyring)
    log.Printf("Passphrase: ", passphrase)

    // Read in public key
    keyringFileBuffer, _ := os.Open(publicKeyring)
    defer keyringFileBuffer.Close()
    entitylist, _ := openpgp.ReadKeyRing(keyringFileBuffer)

    // encrypt string
    buf := new(bytes.Buffer)
    w, _ := openpgp.Encrypt(buf, entitylist, nil, nil, nil)
    w.Write([]byte(mysecretstring))

    // Encode to base64
    bytesp, _ := ioutil.ReadAll(buf)
    encstr := base64.StdEncoding.EncodeToString(bytesp)

    // Output encrypted/encoded string
    log.Printf("Encrypted Secret: ", encstr)

    // Here is where I would transfer the encrypted string to someone else 
    // but we'll just decrypt it in the same code

    // init some vars
    var entity2 *openpgp.Entity
    var entitylist2 openpgp.EntityList

    // Open the private key file
    keyringFileBuffer2, _ := os.Open(secretKeyring)
    defer keyringFileBuffer2.Close()
    entitylist2, _ = openpgp.ReadKeyRing(keyringFileBuffer2)
    entity2 = entitylist2[0]

    // Get the passphrase and read the private key.
    // Have not touched the encrypted string yet
    passphrasebyte := []byte(passphrase)
    log.Printf("Decrypting private key using passphrase")
    entity2.PrivateKey.Decrypt(passphrasebyte)
    for _, subkey := range entity2.Subkeys {
            subkey.PrivateKey.Decrypt(passphrasebyte)
    }
    log.Printf("Finished decrypting private key using passphrase")

    // Decode the base64 string
    dec, _ := base64.StdEncoding.DecodeString(encstr)

    // Decrypt it with the contents of the private key
    md, _ := openpgp.ReadMessage(bytes.NewBuffer(dec), entitylist2, nil, nil)
    bytess, _ := ioutil.ReadAll(md.UnverifiedBody)
    decstr := string(bytess)

    // should be done
    log.Printf("Decrypted Secret: ", decstr)

}

This is based off of https://github.com/jyap808/jaeger

When I run it, it seems to partially work, but only outputs some of the characters of the original string... Changing the original string causes some very weird issues.

2014/09/07 22:59:38 Secret: %!(EXTRA string=this is so very secret!)
2014/09/07 22:59:38 Secret Keyring: %!(EXTRA string=/Users/stuart-warren/.gnupg/secring.gpg)
2014/09/07 22:59:38 Public Keyring: %!(EXTRA string=/Users/stuart-warren/.gnupg/pubring.gpg)
2014/09/07 22:59:38 Passphrase: %!(EXTRA string=1234)
2014/09/07 22:59:38 Encrypted Secret: %!(EXTRA string=wcBMA5a76vUxixWPAQgAOkrt/LQ3u++VbJ/20egxCUzMqcMYtq+JXL7SqbB5S1KrgHhGd8RHUmxy2h45hOLcAt+kfvSz0EJ/EsCmwnbP6HRPEqiMLt6XaVS26Rr9HQHPpRBZkqnwAP0EmlYNnF5zjnU5xTcEOyyr7EYhEgDv0Ro1FQkaCL2xdBhDCXs4EdQsjVrcECWOt0KgbCWs+N/0cEdeyHwodkaDgJ7NMq/pPuviaRu4JHCIxMiyz8yhOCHOM+bI80KsJesjGrgbjnGDfJUZNYDBNc8PqzfC39lB2MBrn/w07thJxvjbep39R0u2C4eEcroTRLB+t9i4fJNiVpoSclYRSZXm5OsYYv/XwtLgAeRZ07lFEsGoHSbqGLUnHFFw4Svk4FPgCuGVpOCS4vYiisDg+ORYj8dpu/Z3gSlVJ6mhSr7H4J3i9vItRuBx4WUB4HHgmQ==)
2014/09/07 22:59:38 Decrypting private key using passphrase
2014/09/07 22:59:38 Finished decrypting private key using passphrase
2014/09/07 22:59:38 Decrypted Secret: %!(EXTRA string=this)

Clearly there is something I'm not understanding, so would appreciate any assistance given.

  • 写回答

2条回答 默认 最新

  • dongquanyu5816 2014-09-10 02:56
    关注

    A reminder that security is unusually treacherous territory, and if there's a way to call on other well-tested code even more of your toplevel task than just what Go's OpenPGP package is handling for you, consider it. It's good that at least low-level details are outsourced to openpgp because they're nasty and so so easy to get wrong. But tiny mistakes at any level can make crypto features worse than useless; if there's a way to write less security-critical code, that's one of the best things anyone can do for security.

    On the specific question: you have to Close() the writer to get everything flushed out (a trait OpenPGP's writer shares with, say, compress/gzip's).

    Unrelated changes: the way you're printing things is a better fit log.Println, which just lets you pass a bunch of values you want printed with spaces in between (like, say, Python print), rather than needing format specifiers like "%s" or "%d". (The "EXTRA" in your initial output is what Go's Printf emits when you pass more things than you had format specifiers for.) It's also best practice to check errors (I dropped if err != nils where I saw a need, but inelegantly and without much thought, and I may not have gotten all the calls) and to run go fmt on your code.

    Again, I can't testify to the seaworthiness of this code or anything like that. But now it round-trips all the text. I wound up with:

    package main
    
    import (
        "bytes"
        "code.google.com/p/go.crypto/openpgp"
        "encoding/base64"
        "io/ioutil"
        "log"
        "os"
    )
    
    // create gpg keys with
    // $ gpg --gen-key
    // ensure you correct paths and passphrase
    
    const mysecretstring = "this is so very secret!"
    const prefix, passphrase = "/Users/stuart-warren/", "1234"
    const secretKeyring = prefix + ".gnupg/secring.gpg"
    const publicKeyring = prefix + ".gnupg/pubring.gpg"
    
    func encTest() error {
        log.Println("Secret:", mysecretstring)
        log.Println("Secret Keyring:", secretKeyring)
        log.Println("Public Keyring:", publicKeyring)
        log.Println("Passphrase:", passphrase)
    
        // Read in public key
        keyringFileBuffer, _ := os.Open(publicKeyring)
        defer keyringFileBuffer.Close()
        entitylist, err := openpgp.ReadKeyRing(keyringFileBuffer)
        if err != nil {
            return err
        }
    
        // encrypt string
        buf := new(bytes.Buffer)
        w, err := openpgp.Encrypt(buf, entitylist, nil, nil, nil)
        if err != nil {
            return err
        }
        _, err = w.Write([]byte(mysecretstring))
        if err != nil {
            return err
        }
        err = w.Close()
        if err != nil {
            return err
        }
    
        // Encode to base64
        bytesp, err := ioutil.ReadAll(buf)
        if err != nil {
            return err
        }
        encstr := base64.StdEncoding.EncodeToString(bytesp)
    
        // Output encrypted/encoded string
        log.Println("Encrypted Secret:", encstr)
    
        // Here is where I would transfer the encrypted string to someone else
        // but we'll just decrypt it in the same code
    
        // init some vars
        var entity2 *openpgp.Entity
        var entitylist2 openpgp.EntityList
    
        // Open the private key file
        keyringFileBuffer2, err := os.Open(secretKeyring)
        if err != nil {
            return err
        }
        defer keyringFileBuffer2.Close()
        entitylist2, err = openpgp.ReadKeyRing(keyringFileBuffer2)
        if err != nil {
            return err
        }
        entity2 = entitylist2[0]
    
        // Get the passphrase and read the private key.
        // Have not touched the encrypted string yet
        passphrasebyte := []byte(passphrase)
        log.Println("Decrypting private key using passphrase")
        entity2.PrivateKey.Decrypt(passphrasebyte)
        for _, subkey := range entity2.Subkeys {
            subkey.PrivateKey.Decrypt(passphrasebyte)
        }
        log.Println("Finished decrypting private key using passphrase")
    
        // Decode the base64 string
        dec, err := base64.StdEncoding.DecodeString(encstr)
        if err != nil {
            return err
        }
    
        // Decrypt it with the contents of the private key
        md, err := openpgp.ReadMessage(bytes.NewBuffer(dec), entitylist2, nil, nil)
        if err != nil {
            return err
        }
        bytess, err := ioutil.ReadAll(md.UnverifiedBody)
        if err != nil {
            return err
        }
        decstr := string(bytess)
    
        // should be done
        log.Println("Decrypted Secret:", decstr)
    
        return nil
    }
    
    func main() {
        err := encTest()
        if err != nil {
            log.Fatal(err)
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮