2

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.

4

2 回答 2

7

提醒一下,安全性是非常危险的领域,如果有一种方法可以调用其他经过良好测试的代码,甚至比 Go 的 OpenPGP 包为您处理的任务更多,请考虑一下。至少将低级别的细节外包给他们是件好事,openpgp因为它们很讨厌而且很容易出错。但是任何级别的微小错误都可能使加密功能变得更糟。如果有办法编写对安全性要求不高的代码,那将是任何人都可以为安全做的最好的事情之一。

关于具体问题:你必须让Close()作者把所有东西都冲洗掉(OpenPGP 的作者与compress/gzip's 分享的一个特征)。

不相关的变化:你打印东西的方式更合适log.Println,它只允许你传递一堆你想要打印的值,中间有空格(比如 Python print),而不需要像"%s"or之类的格式说明符"%d"。(初始输出中的“EXTRA”是 GoPrintf在传递的内容多于格式说明符时发出的内容。)检查错误也是最佳实践(我if err != nil在看到需要的地方删除了 s,但不雅且没有太多考虑,而且我可能没有接到所有电话)并go fmt在您的代码上运行。

同样,我无法证明此代码或类似代码的适航性。但现在它往返所有文本。我结束了:

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)
    }
}
于 2014-09-10T02:56:20.360 回答
0

我无法测试您的代码,但我唯一能想到的是执行顺序错误。您首先制作一个字符串,然后将其制作为 Base64,然后对其进行加密。现在撤消 Base64,然后解密编码的字符串。最后两个必须交换。

于 2014-09-08T00:49:31.253 回答