I'm confused about the HTTP API docs of IPFS。next is part of it。
/api/v0/add
Add a file or directory to IPFS.
//but how to add a directory by golang? it look like so simple but no a example to finish it
#cURL Example
curl -X POST -F file=#myfile "http://127.0.0.1:5001/api/v0/add?quiet=&quieter=&silent=&progress=&trickle=&only-hash=&wrap-with-directory=&chunker=size-262144&pin=true&raw-leaves=&nocopy=&fscache=&cid-version=&hash=sha2-256&inline=&inline-limit=32"
I worked on the same issue and found this working shell solution:
https://community.infura.io/t/ipfs-http-api-add-directory/189/8
you can rebuild this in go
package main
import (
"bytes"
"github.com/stretchr/testify/assert"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
"strings"
"testing"
)
func TestUploadFolderRaw(t *testing.T) {
ct, r, err := createForm(map[string]string{
"/file1": "#/my/path/file1",
"/dir": "#/my/path/dir",
"/dir/file": "#/my/path/dir/file",
})
assert.NoError(t, err)
resp, err := http.Post("http://localhost:5001/api/v0/add?pin=true&recursive=true&wrap-with-directory=true", ct, r)
assert.NoError(t, err)
respAsBytes, err := ioutil.ReadAll(resp.Body)
assert.NoError(t, err)
t.Log(string(respAsBytes))
}
func createForm(form map[string]string) (string, io.Reader, error) {
body := new(bytes.Buffer)
mp := multipart.NewWriter(body)
defer mp.Close()
for key, val := range form {
if strings.HasPrefix(val, "#") {
val = val[1:]
file, err := os.Open(val)
if err != nil { return "", nil, err }
defer file.Close()
part, err := mp.CreateFormFile(key, val)
if err != nil { return "", nil, err }
io.Copy(part, file)
} else {
mp.WriteField(key, val)
}
}
return mp.FormDataContentType(), body, nil
}
or use https://github.com/ipfs/go-ipfs-http-client which seems to be a better way. I'm working on it and tell you when I know how to use it
Greetings
I am trying to encrypt a file using the Go crypto/aes package. I have so far:
func encrypt(source string, localdir string) error {
src := filepath.Join("/home/bacula/cloud-backup/"+localdir, source)
dst := filepath.Join(src + ".aes")
fmt.Println(src)
fmt.Println(dst)
key := []byte("example key 1234")
iv := []byte(key)[:aes.BlockSize]
aesBlockEncrypter, err := aes.NewCipher([]byte(key))
if err != nil {
return err
}
aesEncrypter := cipher.NewCFBEncrypter(aesBlockEncrypter, iv)
aesEncrypter.XORKeyStream([]byte(dst), []byte(src))
return nil
}
My first question is, how can I improve the way I am generating the IV? And secondly, there is no output file, so how do I stream the file through XORKeyStream?
There is an example in the crypto/cipher package documentation.
I've tweaked the example to make new example for you:
func main() {
// read content from your file
plaintext, err := ioutil.ReadFile("you_file_to_be_encrypted")
if err != nil {
panic(err.Error())
}
// this is a key
key := []byte("example key 1234")
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
// create a new file for saving the encrypted data.
f, err := os.Create("a_aes.txt")
if err != nil {
panic(err.Error())
}
_, err = io.Copy(f, bytes.NewReader(ciphertext))
if err != nil {
panic(err.Error())
}
// done
}
I'm using code.google.com/p/go.crypto/twofish and I want to decrypt password, which I get from database. The password was encrypt by PHP and it's encoded by base64. In Go, I decode by base64, convert to []byte and I tried decrypt it, but something was going right. My return is empty. It's my code:
func TwofishDecrypt(key, text []byte) ([]byte, error) {
block, err := twofish.NewCipher(key)
if err != nil {
return nil, err
}
if len(text) < twofish.BlockSize {
return nil, errors.New("ciphertext too short")
}
iv := text[:twofish.BlockSize]
text = text[twofish.BlockSize:]
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(text, text)
data, err := base64.StdEncoding.DecodeString(string(text))
if err != nil {
return nil, err
}
return data, nil
}
I am developing a simple Go server program which receives client's request and process it. And the code is simplified as this:
package main
import (
"fmt"
"net"
"os"
)
const (
pduLen = 32
)
func checkError(err error) {
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func main() {
var buffer [4096]byte
var count int
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%s", os.Args[1], os.Args[2]))
checkError(err)
for count < pduLen {
n, err := conn.Read(buffer[count:])
checkError(err)
count += n
}
......
}
I assume every request's length is 32 bytes (just an example). Because the TCP is a stream protocol, I need to use a loop to check whether an integral PDU is read:
for count < pduLen {
n, err := conn.Read(buffer[count:])
checkError(err)
count += n
}
Is there any method to assure that an integral PDU is read? Personally, I think the loop code is a little ugly.
It can depend on the exact nature of the PDU you are receiving, but this example will look for the size, and then read everything (using io.ReadFul()).
func read(conn net.Conn, key string) string {
fmt.Fprintf(conn, GenerateCommand(OP_GET, key))
if verify(conn) {
var size uint16
binary.Read(conn, binary.LittleEndian, &size)
b := make([]byte, size)
// _, err := conn.Read(b)
_, err := io.ReadFull(conn, b)
if err == nil {
return string(b)
}
}
return ""
}
func verify(conn net.Conn) bool {
b := make([]byte, 1)
conn.Read(b)
return b[0] == ERR_NO_ERROR
}
Used in:
conn, err := net.Dial("tcp", ":12345")
if err != nil {
t.Error(err)
}
write(conn, "foo", "bar")
if !verify(conn) {
t.Error("Bad write!")
}
if r := read(conn, "foo"); r != "bar" {
t.Errorf("Bad read! Got %v", r)
}
After discussing this issue in golang-nuts: How to read an integral network PDU?
The code should be:
import "io"
......
pdu := make([]byte, pduLen)
io.ReadFull(conn, pdu)
I'm trying to encrypt some text inside a database to be loaded and decrypted during program startup.
I have tried a few methods, including a third party library https://github.com/richard-lyman/lithcrypt to no avail. Using the following method encrypts/decrypts 8/10 items, but it seems that some padding residue is left behind at some point in the encrypt/decrypt. As it stands my code is like this:
package client
import (
"encoding/base64"
"crypto/aes"
"crypto/cipher"
"fmt"
)
var iv = []byte{34, 35, 35, 57, 68, 4, 35, 36, 7, 8, 35, 23, 35, 86, 35, 23}
func encodeBase64(b []byte) string {
return base64.StdEncoding.EncodeToString(b)
}
func decodeBase64(s string) []byte {
data, err := base64.StdEncoding.DecodeString(s)
if err != nil { panic(err) }
return data
}
func Encrypt(key, text string) string {
block, err := aes.NewCipher([]byte(key))
if err != nil { panic(err) }
plaintext := []byte(text)
cfb := cipher.NewCFBEncrypter(block, iv)
ciphertext := make([]byte, len(plaintext))
cfb.XORKeyStream(ciphertext, plaintext)
return encodeBase64(ciphertext)
}
func Decrypt(key, text string) string {
block, err := aes.NewCipher([]byte(key))
if err != nil { panic(err) }
ciphertext := decodeBase64(text)
cfb := cipher.NewCFBEncrypter(block, iv)
plaintext := make([]byte, len(ciphertext))
cfb.XORKeyStream(plaintext, ciphertext)
}
It was mentioned to me that I might need to pad the string, but it seems strange that I would have to pad a stream cipher.
Below is an example of this error: http://play.golang.org/p/4FQBAeHgRs
This is based on the NewCFBEncrypter / NewCFBDecrypter examples and seems to do what you require:
EDIT: Based on Kluyg's comment regarding IV creation I've modified the example code to use the recommended method of creating the IV from the ciphertext same method as the linked example to create the IV from the ciphertext. (In production code the IV should be generated seperately each time. Thanks to RoundSparrow hilltx for pointing this out.)
I think the problem you're encountering is due to an invalid key length, but I'm not 100% sure.
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"io"
"log"
)
func main() {
key := []byte("a very very very very secret key") // 32 bytes
plaintext := []byte("some really really really long plaintext")
fmt.Printf("%s\n", plaintext)
ciphertext, err := encrypt(key, plaintext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%0x\n", ciphertext)
result, err := decrypt(key, ciphertext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", result)
}
// See alternate IV creation from ciphertext below
//var iv = []byte{35, 46, 57, 24, 85, 35, 24, 74, 87, 35, 88, 98, 66, 32, 14, 05}
func encrypt(key, text []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
b := base64.StdEncoding.EncodeToString(text)
ciphertext := make([]byte, aes.BlockSize+len(b))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
return ciphertext, nil
}
func decrypt(key, text []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
if len(text) < aes.BlockSize {
return nil, errors.New("ciphertext too short")
}
iv := text[:aes.BlockSize]
text = text[aes.BlockSize:]
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(text, text)
data, err := base64.StdEncoding.DecodeString(string(text))
if err != nil {
return nil, err
}
return data, nil
}
Produces:
some really really really long plaintext
54618bd6bb10612a7b590c53192df214501e01b685540b012581a0ed9ff3ddaa1f4177cc6186b501fb8cce0c2eb764daff475aab724d4d33e614d7d89cf556d8512fd920018c090f
some really really really long plaintext
Playground
Crypto is hard and the go libraries are perhaps not high level enough so it's easy to make mistakes.
For anyone looking for an example of doing it right by an expert in the field (a security developer at CoreOS), this gives a good example of AES encryption (along with other common uses of crypto).
https://github.com/gtank/cryptopasta
Here is the working demo i just finished writing, it mostly uses code samples from the go document but it is tailored to do what most apps including my use case expects out of encryption methods.
It use AES encryption.
encrypt from string to base64 string. Easy to use on URL and dbs.
decrypt from base64 string created above to original text.
Simple text conversions everywhere.
GIST: Here is the gist, please let me know if there are any need for the improvements.
It's a simple go file, ready to be run.
It appears your order of operations are a bit backwards. Here is what you appear to be doing:
ct = encrypt(encode(pt))
pt = decode(decrypt(ct))
It should look more like:
ct = encode(encrypt(pt))
pt = decrypt(decode(ct))
The following works for me
func Encrypt(key, text []byte) string {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
ciphertext := make([]byte, aes.BlockSize+len(text))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(crand.Reader, iv); err != nil {
panic(err)
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream(ciphertext[aes.BlockSize:], text)
return encodeBase64(ciphertext)
}
func Decrypt(key []byte, b64 string) string {
text := decodeBase64(b64)
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
if len(text) < aes.BlockSize {
panic("ciphertext too short")
}
iv := text[:aes.BlockSize]
text = text[aes.BlockSize:]
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(text, text)
return string(text)
}
Many have already provided nice answers. But as #PiersyP has pointed in the comments on #Intermernet 's answer, there's no need to base64 the text. So here it is without base64ing in case someone is in rush
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"errors"
"fmt"
"io"
"log"
)
func main() {
key := []byte("a very very very very secret key") // 32 bytes
plaintext := []byte("some really really really long plaintext")
fmt.Printf("%s\n", plaintext)
ciphertext, err := encrypt(key, plaintext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%0x\n", ciphertext)
result, err := decrypt(key, ciphertext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", result)
}
// See alternate IV creation from ciphertext below
//var iv = []byte{35, 46, 57, 24, 85, 35, 24, 74, 87, 35, 88, 98, 66, 32, 14, 05}
func encrypt(key, text []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
ciphertext := make([]byte, aes.BlockSize + len(text))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream(ciphertext[aes.BlockSize:], text)
return ciphertext, nil
}
func decrypt(key, text []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
if len(text) < aes.BlockSize {
return nil, errors.New("ciphertext too short")
}
iv := text[:aes.BlockSize]
text = text[aes.BlockSize:]
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(text, text)
return text, nil
}
Not actually answer to the question. But I put a full working example here for someone who comes from search engines.
Twisted from gtank/cryptopasta by adding a hash password. You can use any password without worrying about its size.
Go Playground
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"errors"
"fmt"
"io"
)
func main() {
key := []byte("secret")
ct, err := Encrypt([]byte("Plain text"), key)
if err != nil {
panic(err)
}
fmt.Println("Encrypted:", base64.StdEncoding.EncodeToString(ct))
pt, err := Decrypt(ct, key)
if err != nil {
panic(err)
}
fmt.Println("Decrypted:", string(pt))
}
// Encrypt encrypts data using 256-bit AES-GCM. This both hides the content of
// the data and provides a check that it hasn't been altered. Output takes the
// form nonce|ciphertext|tag where '|' indicates concatenation.
func Encrypt(plaintext []byte, key []byte) (ciphertext []byte, err error) {
k := sha256.Sum256(key)
block, err := aes.NewCipher(k[:])
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
_, err = io.ReadFull(rand.Reader, nonce)
if err != nil {
return nil, err
}
return gcm.Seal(nonce, nonce, plaintext, nil), nil
}
// Decrypt decrypts data using 256-bit AES-GCM. This both hides the content of
// the data and provides a check that it hasn't been altered. Expects input
// form nonce|ciphertext|tag where '|' indicates concatenation.
func Decrypt(ciphertext []byte, key []byte) (plaintext []byte, err error) {
k := sha256.Sum256(key)
block, err := aes.NewCipher(k[:])
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(ciphertext) < gcm.NonceSize() {
return nil, errors.New("malformed ciphertext")
}
return gcm.Open(nil,
ciphertext[:gcm.NonceSize()],
ciphertext[gcm.NonceSize():],
nil,
)
}