failure in go.crypto and GnuPG interoperability
Bernd Fix
brf at hoi-polloi.org
Thu Jan 30 13:30:57 CET 2014
I am working on an application that is encrypting content with the
openpgp functions from the go.crypto framework. This content is later to
be decrypted using the GnuPG application on a Linux box. There seems to
be an incompatibility between go.crypto and the GnuPG that fails to
decrypt the original content correctly - the decrypted content for
larger files is smaller than the original input.
I am using Debian7 with the tip version of Go, the current go.crypto
repository and GnuPG 1.4.12. The following steps will reproduce the problem:
(1) create a file with random content (1MB in this case):
dd if=/dev/urandom of=xxx.in count=2048
(2) create a local keyring for testing:
gpg --home . --gen-key
I used RSA-4096 keys and "testtest" as a password; if you use a
different password, change the source code of the test app; create only
one key in the keyring!
(3) compile the test app from the source code below:
go build test.go
(4) Run the test app:
./test
The output "Compare: 0" indicates that the encryption/decryption cycle
in go.crypto worked fine and delivered the expected result.
(5) Decrypt output using GnuPG:
gpg --home . -o xxx.out -d xxx.in.gpg
Compare the two files; you will see something like:
-rw-r--r-- 1 test test 1048576 Jan 30 13:06 xxx.in
-rw-r--r-- 1 test test 1044505 Jan 30 13:18 xxx.out
The two files don't match and neither the test app nor GnuPG showed any
warning or error message. Am I doing something wrong or what is going on
here?
Regards, Bernd.
=====[test.go]=================================================
package main
import (
"bytes"
"code.google.com/p/go.crypto/openpgp"
"fmt"
"io"
"io/ioutil"
"os"
)
const (
FILE = "xxx.in"
GNUPG = "secring.gpg"
PASSP = "testtest"
)
func main() {
rdr, err := os.Open(GNUPG)
if err != nil {
panic(err.Error())
}
defer rdr.Close()
ents, err := openpgp.ReadKeyRing(rdr)
if err != nil {
panic(err.Error())
}
f, err := os.Open(FILE)
if err != nil {
panic(err.Error())
}
plain, err := ioutil.ReadAll(f)
if err != nil {
panic(err.Error())
}
cBuf := new(bytes.Buffer)
cWrt, err := openpgp.Encrypt(cBuf, ents, nil, nil, nil)
if err != nil {
panic(err.Error())
}
cWrt.Write(plain)
cWrt.Close()
cipher := cBuf.Bytes()
out, err := os.Create(FILE + ".gpg")
if err != nil {
panic(err.Error())
}
out.Write(cipher)
out.Close()
cBuf = bytes.NewBuffer(cipher)
pBuf := new(bytes.Buffer)
md, err := openpgp.ReadMessage(
cBuf,
ents,
func(keys []openpgp.Key, symmetric bool) ([]byte, error) {
priv := keys[0].PrivateKey
if priv.Encrypted {
priv.Decrypt([]byte(PASSP))
}
buf := new(bytes.Buffer)
priv.Serialize(buf)
return buf.Bytes(), nil
},
nil)
if err != nil {
panic(err.Error())
}
buf := make([]byte, 1024)
for {
n, err := md.UnverifiedBody.Read(buf)
pBuf.Write(buf[:n])
if err != nil {
if err == io.EOF {
err = nil
break
}
panic(err.Error())
}
}
plain2 := pBuf.Bytes()
fmt.Printf("Compare: %d\n", bytes.Compare(plain, plain2))
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 551 bytes
Desc: OpenPGP digital signature
URL: </pipermail/attachments/20140130/ada41034/attachment.sig>
More information about the Gnupg-devel
mailing list