/
encrypt.go
110 lines (92 loc) · 2.31 KB
/
encrypt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package main
import (
"archive/tar"
"crypto/rand"
"fmt"
"github.com/gja/openssl"
"io"
"log"
)
func randomBytes(num int) (key []byte) {
key = make([]byte, num, num)
n, err := rand.Read(key)
if err != nil || n != num {
log.Fatalln(err)
}
return key
}
type EncryptionWriter struct {
err error
wr *tar.Writer
ctx openssl.EncryptionCipherCtx
count int
}
func (writer *EncryptionWriter) writeToTar(name string, toWrite []byte) {
err := writer.wr.WriteHeader(&tar.Header{Name: name, Size: int64(len(toWrite))})
if err != nil {
log.Fatalln(err)
}
_, err = writer.wr.Write(toWrite)
if err != nil {
log.Fatalln(err)
}
}
func (writer *EncryptionWriter) Write(data []byte) (int, error) {
if writer.err != nil {
return 0, writer.err
}
toWrite, err := writer.ctx.EncryptUpdate(data)
if err != nil {
writer.err = err
log.Fatalln(err)
}
writer.writeToTar(fmt.Sprintf("value%d", writer.count), toWrite)
writer.count += 1
return len(data), err
}
func (writer *EncryptionWriter) finish() {
toWrite, err := writer.ctx.EncryptFinal()
if err != nil {
writer.err = err
log.Fatalln(err)
}
writer.writeToTar("close", toWrite)
writer.wr.Flush()
writer.wr.Close()
}
func encryptKey(key []byte, privateKey *openssl.PublicKey) []byte {
rsaSize, err := (*privateKey).RSASize()
if err != nil {
log.Fatalln(err)
}
outputBytes := make([]byte, rsaSize)
len, err := (*privateKey).PublicEncrypt(outputBytes, key, openssl.RSA_PADDING_PKCS1)
if err != nil {
log.Fatalln(err)
}
output := make([]byte, len)
copy(output, outputBytes)
return output
}
func newEncryptionWriter(publicKey *openssl.PublicKey, output io.Writer) *EncryptionWriter {
cipher, err := openssl.GetCipherByName("aes-256-cbc")
if err != nil {
log.Fatalln(err)
}
key := randomBytes(cipher.KeySize())
iv := randomBytes(cipher.IVSize())
ctx, err := openssl.NewEncryptionCipherCtx(cipher, nil, key, iv)
if err != nil {
log.Fatalln(err)
}
tarFile := tar.NewWriter(output)
writer := &EncryptionWriter{wr: tarFile, ctx: ctx}
writer.writeToTar("key", encryptKey(key, publicKey))
writer.writeToTar("iv", iv)
return writer
}
func Encrypt(publicKey *openssl.PublicKey, input io.ReadCloser, output io.WriteCloser) {
encryptionWriter := newEncryptionWriter(publicKey, output)
io.Copy(encryptionWriter, input)
encryptionWriter.finish()
}