From e9260b01d0700faae73ced837f4a1301d9dac2d2 Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Thu, 2 May 2019 10:08:20 -0600 Subject: [PATCH] base --- .gitignore | 4 + encryptor.go | 384 ++++++++++++++++++++++++++++++++++++++++++++++ encryptor_test.go | 87 +++++++++++ first | 102 ++++++++++++ second | 156 +++++++++++++++++++ 5 files changed, 733 insertions(+) create mode 100755 .gitignore create mode 100755 encryptor.go create mode 100755 encryptor_test.go create mode 100755 first create mode 100755 second diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..fb3eb24 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +alt* +*.swp +*.swo +encryptor diff --git a/encryptor.go b/encryptor.go new file mode 100755 index 0000000..2f24c25 --- /dev/null +++ b/encryptor.go @@ -0,0 +1,384 @@ +package encryptor + +import ( + "bytes" + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" + "errors" + "io" + "io/ioutil" + "os" + "path" + "strings" + + "golang.org/x/crypto/openpgp" + "golang.org/x/crypto/openpgp/packet" + // for openpgp + _ "golang.org/x/crypto/ripemd160" +) + +const keylen = 32 + +// Encryptor interface +type Encryptor interface { + Encrypt(string) string + Decrypt(string) string + SetPublic(string) + GetPublic() string + SetSymmetric(string) + + FromFiles(string, string) error + ToFiles(string, string) error +} + +type encryptor struct { + entity *openpgp.Entity + writing *openpgp.Entity + symmetric string + b64 bool +} + +func (e *encryptor) SetPublic(pub string) { + reader := b64dec(pub) + e.writing = entityFromPackets(nil, strToPubPack(reader)) +} + +func (e *encryptor) GetPublic() string { + bufpub := new(bytes.Buffer) + e.writing.Serialize(bufpub) + bufPu, err := ioutil.ReadAll(bufpub) + if err != nil { + panic(err) + } + return b64enc(string(bufPu)) +} + +func (e *encryptor) setPrivate(pri string) { + readerPri := b64dec(pri) + readerPub := b64dec(e.GetPublic()) + e.entity = entityFromPackets(strToPriPack(readerPri), strToPubPack(readerPub)) +} + +func (e *encryptor) getPrivate() string { + bufpri := new(bytes.Buffer) + e.entity.SerializePrivate(bufpri, nil) + bufPr, err := ioutil.ReadAll(bufpri) + if err != nil { + panic(err) + } + return b64enc(string(bufPr)) +} + +// NewKeyPair generates a PGP private-public key pair. +func NewKeyPair() (string, string) { + entity, err := openpgp.NewEntity("", "", "", nil) + if err != nil { + panic(err) + } + en := &encryptor{ + entity: entity, + writing: entity, + } + return en.getPrivate(), en.GetPublic() +} + +func (e *encryptor) getPubPacket() *packet.PublicKey { + return e.writing.PrimaryKey +} + +func (e *encryptor) getPriPacket() *packet.PrivateKey { + return e.entity.PrivateKey +} + +func entityFromPackets(priKey *packet.PrivateKey, pubKey *packet.PublicKey) *openpgp.Entity { + config := packet.Config{ + DefaultHash: crypto.SHA256, + DefaultCipher: packet.CipherAES256, + DefaultCompressionAlgo: packet.CompressionZLIB, + CompressionConfig: &packet.CompressionConfig{ + Level: 9, + }, + RSABits: 4096, + } + + currentTime := config.Now() + uid := packet.NewUserId("", "", "") + + e := openpgp.Entity{ + PrimaryKey: pubKey, + PrivateKey: priKey, + Identities: make(map[string]*openpgp.Identity), + } + isPrimaryID := false + + e.Identities[uid.Id] = &openpgp.Identity{ + Name: uid.Name, + UserId: uid, + SelfSignature: &packet.Signature{ + CreationTime: currentTime, + SigType: packet.SigTypePositiveCert, + PubKeyAlgo: packet.PubKeyAlgoRSA, + Hash: config.Hash(), + IsPrimaryId: &isPrimaryID, + FlagsValid: true, + FlagSign: true, + FlagCertify: true, + IssuerKeyId: &e.PrimaryKey.KeyId, + }, + } + + keyLifetimeSecs := uint32(86400 * 365) + + e.Subkeys = make([]openpgp.Subkey, 1) + e.Subkeys[0] = openpgp.Subkey{ + PublicKey: pubKey, + PrivateKey: priKey, + Sig: &packet.Signature{ + CreationTime: currentTime, + SigType: packet.SigTypeSubkeyBinding, + PubKeyAlgo: packet.PubKeyAlgoRSA, + Hash: config.Hash(), + PreferredHash: []uint8{8}, // SHA-256 + FlagsValid: true, + FlagEncryptStorage: true, + FlagEncryptCommunications: true, + IssuerKeyId: &e.PrimaryKey.KeyId, + KeyLifetimeSecs: &keyLifetimeSecs, + }, + } + return &e + +} + +func strToPack(str string) interface{} { + reader := b64dec(str) + KeyRead := bytes.NewReader([]byte(reader)) + PacketReader := packet.NewReader(KeyRead) + pkt, err := PacketReader.Next() + if err != nil { + panic(err) + } + return pkt +} + +func strToPriPack(private string) *packet.PrivateKey { + priKeyPack, ok := strToPack(private).(*packet.PrivateKey) + if !ok { + panic(ok) + } + return priKeyPack +} + +func strToPubPack(public string) *packet.PublicKey { + pubKeyPack, ok := strToPack(public).(*packet.PublicKey) + if !ok { + panic(ok) + } + return pubKeyPack +} + +// NewEncryptor function +func NewEncryptor(private, public string, b64 ...bool) *encryptor { + backupPri, backupPub := NewKeyPair() + if private == "" { + private = backupPri + } + if public == "" { + public = backupPub + } + priKeyPack := strToPriPack(private) + pubKeyPack := strToPubPack(public) + + b64payloads := len(b64) > 0 && b64[0] + + return &encryptor{ + entity: entityFromPackets(priKeyPack, pubKeyPack), + writing: entityFromPackets(nil, pubKeyPack), + b64: b64payloads, + } +} + +func b64enc(msg string) string { + return base64.StdEncoding.EncodeToString([]byte(msg)) +} + +func b64dec(msg string) string { + decMe, err := base64.StdEncoding.DecodeString(msg) + if err != nil { + return msg + } + return string(decMe) +} + +func (e *encryptor) SetSymmetric(key string) { + e.symmetric = key +} + +func (e *encryptor) Encrypt(msg string) string { + if e.symmetric != "" { + return e.symEncrypt(msg) + } + return e.asymEncrypt(msg) +} + +func (e *encryptor) Decrypt(msg string) string { + if e.symmetric != "" { + return e.symDecrypt(msg) + } + return e.asymDecrypt(msg) +} + +func fixKey(key string) []byte { + return []byte(strings.Repeat("minkey"+string(key), keylen)[:keylen]) +} + +func pad(src []byte) []byte { + padding := aes.BlockSize - len(src)%aes.BlockSize + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + return append(src, padtext...) +} + +func unpad(src []byte) ([]byte, error) { + length := len(src) + unpadding := int(src[length-1]) + + if unpadding > length { + return nil, errors.New("unpad error. This could happen when incorrect encryption key is used") + } + + return src[:(length - unpadding)], nil +} + +func (e *encryptor) symEncrypt(smsg string) string { + key := fixKey(e.symmetric) + block, err := aes.NewCipher(key) + if err != nil { + return "" + } + + msg := pad([]byte(smsg)) + ciphertext := make([]byte, aes.BlockSize+len(msg)) + iv := ciphertext[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + return "" + } + + cfb := cipher.NewCFBEncrypter(block, iv) + cfb.XORKeyStream(ciphertext[aes.BlockSize:], msg) + if e.b64 { + return b64enc(string(ciphertext)) + } + return string(ciphertext) +} + +func (e *encryptor) symDecrypt(msg string) string { + payload := []byte(msg) + if e.b64 { + payload = []byte(b64dec(msg)) + } + if len(payload) == 0 { + return "" + } + key := fixKey(e.symmetric) + block, err := aes.NewCipher(key) + if err != nil { + return "" + } + + if (len(payload) % aes.BlockSize) != 0 { + return "" + } + + iv := payload[:aes.BlockSize] + bmsg := payload[aes.BlockSize:] + + cfb := cipher.NewCFBDecrypter(block, iv) + cfb.XORKeyStream(bmsg, bmsg) + + b, _ := unpad(bmsg) + return string(b) +} + +// Encrypt function +func (e *encryptor) asymEncrypt(msg string) string { + // encrypt string + buf := new(bytes.Buffer) + w, err := openpgp.Encrypt(buf, []*openpgp.Entity{e.writing}, nil, nil, nil) + if err != nil { + return "" + } + _, err = w.Write([]byte(msg)) + if err != nil { + return "" + } + err = w.Close() + if err != nil { + return "" + } + // Encode to b64 + return b64enc(string(buf.Bytes())) +} + +// Decrypt function +func (e *encryptor) asymDecrypt(msg string) string { + // Decode the b64 string + decMe := b64dec(msg) + KeyRead := bytes.NewReader([]byte(decMe)) + + md, err := openpgp.ReadMessage(KeyRead, openpgp.EntityList([]*openpgp.Entity{e.entity}), nil, nil) + if err != nil { + return "" + } + + plaintext, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + return "" + } + + return string(plaintext) +} + +func (e *encryptor) FromFiles(privatePath, publicPath string) error { + priRaw, err := ioutil.ReadFile(privatePath) + if err != nil { + return err + } + pubRaw, err := ioutil.ReadFile(publicPath) + if err != nil { + return err + } + + d := NewEncryptor(string(priRaw), string(pubRaw)) + + v := d.Encrypt("Hello") + if len(v) == 0 { + return errors.New("bad public-private key file pair") + } + v = d.Decrypt(v) + if len(v) == 0 { + return errors.New("bad public-private key file pair") + } + e.entity = d.entity + e.writing = d.entity + return nil +} + +func (e *encryptor) ToFiles(privatePath, publicPath string) error { + d := &encryptor{ + writing: e.entity, + entity: e.entity, + } + if err := os.MkdirAll(path.Dir(privatePath), os.ModePerm); err != nil { + return err + } + if err := ioutil.WriteFile(privatePath, []byte(d.getPrivate()), os.ModePerm); err != nil { + return err + } + if err := os.MkdirAll(path.Dir(publicPath), os.ModePerm); err != nil { + return err + } + return ioutil.WriteFile(publicPath, []byte(d.GetPublic()), os.ModePerm) +} diff --git a/encryptor_test.go b/encryptor_test.go new file mode 100755 index 0000000..4cb2c49 --- /dev/null +++ b/encryptor_test.go @@ -0,0 +1,87 @@ +package encryptor + +import ( + "io/ioutil" + "os" + "testing" +) + +func Test_Encrypter_ToFromFiles(t *testing.T) { + pubFile, err := ioutil.TempFile(".", "test_pub***.key") + if err != nil { + t.Fatalf("could not create temp pub file " + err.Error()) + } + defer os.Remove(pubFile.Name()) + + priFile, err := ioutil.TempFile(".", "test_pri***.key") + if err != nil { + t.Fatalf("could not create temp pri file " + err.Error()) + } + defer os.Remove(priFile.Name()) + + e := NewEncryptor("", "") + if err := e.ToFiles(priFile.Name(), pubFile.Name()); err != nil { + t.Fatalf("Could not save to files: %v", err) + } + if err := e.FromFiles(priFile.Name(), pubFile.Name()); err != nil { + t.Fatalf("Could not load from files: %v", err) + } + + tocrypt := "can you hear" + encrypted := e.Encrypt(tocrypt) + if len(encrypted) == 0 { + t.Fatalf("cannot encrypt after fromFiles") + } + decrypted := e.Decrypt(encrypted) + if decrypted != tocrypt { + t.Fatalf("cannot decrypt after fromFiles") + } +} + +func Test_EncrypterSym(t *testing.T) { + private, public := NewKeyPair() + e := NewEncryptor(private, public) + msg := "can you hear me screaming" + e.SetPublic(public) + e.SetSymmetric(e.GetPublic()) + for i := 0; i < 2; i++ { + encrypted := e.Encrypt(msg) + decrypted := e.Decrypt(encrypted) + if decrypted != msg { + t.Errorf("decrypt(enrypt(%v)) not the same", msg) + } + } +} + +func Test_EncryptorAsym(t *testing.T) { + private, public := NewKeyPair() + e := NewEncryptor(private, public) + msg := "can you hear me screaming" + e.SetPublic(public) + e.SetSymmetric("") + for i := 0; i < 2; i++ { + encrypted := e.Encrypt(msg) + decrypted := e.Decrypt(encrypted) + if decrypted != msg { + t.Errorf("decrypt(enrypt(%v)) not the same", msg) + } + } +} + +func Test_GetSet(t *testing.T) { + privateA, publicA := NewKeyPair() + privateB, publicB := NewKeyPair() + eA := NewEncryptor(privateA, publicA) + eB := NewEncryptor(privateB, publicB) + + eA.SetPublic(publicB) + //eB.SetPublic(publicA) + + msg := "hello from A to B" + encrypted := eA.Encrypt(msg) + decrypted := eB.Decrypt(encrypted) + + if decrypted != msg { + t.Errorf("decrypt(enrypt(%v)) not the same", msg) + } +} diff --git a/first b/first new file mode 100755 index 0000000..33e00ce --- /dev/null +++ b/first @@ -0,0 +1,102 @@ +package encryptor + +import ( + "bytes" + "encoding/base64" + "fmt" + "io" + "io/ioutil" + + "golang.org/x/crypto/openpgp" + _ "golang.org/x/crypto/ripemd160" +) + +// Encryptor interface +type Encryptor interface { + Encrypt(string) string + Decrypt() string +} + +type encryptor struct { + entity *openpgp.Entity +} + +// NewEncryptor function +func NewEncryptor(private, public string) *encryptor { + entity, err := openpgp.NewEntity("", "", "", nil) + if err != nil { + panic(err) + } + entity.PrimaryKey.PubKeyAlgo + entity.PrimaryKey.PublicKey + entity.PrivateKey.PubKeyAlgo + entity.PrivateKey.PrivateKey + fmt.Println(fmt.Sprintf("%T", entity.PrimaryKey.PublicKey)) + bufpri := new(bytes.Buffer) + entity.SerializePrivate(bufpri, nil) + bufpub := new(bytes.Buffer) + entity.Serialize(bufpub) + bufPr, _ := b64enc(bufpri) + bufPu, _ := b64enc(bufpub) + fmt.Printf("PRIVATE: %v\nPUBLIC: %v\n", bufPr[10:20], bufPu[10:20]) + return &encryptor{ + entity: entity, + } +} + +func b64enc(msg io.Reader) (string, error) { + bytes, err := ioutil.ReadAll(msg) + if err != nil { + return "", err + } + return base64.StdEncoding.EncodeToString(bytes), nil +} + +func b64dec(msg string) (io.Reader, error) { + decMe, err := base64.StdEncoding.DecodeString(msg) + if err != nil { + return nil, err + } + return bytes.NewBuffer(decMe), nil +} + +// Encrypt function +func (e *encryptor) Encrypt(msg string) (string, error) { + // encrypt string + buf := new(bytes.Buffer) + w, err := openpgp.Encrypt(buf, []*openpgp.Entity{e.entity}, nil, nil, nil) + if err != nil { + return "", err + } + _, err = w.Write([]byte(msg)) + if err != nil { + return "", err + } + err = w.Close() + if err != nil { + return "", err + } + // Encode to base64 + return b64enc(buf) +} + +// Decrypt function +func (e *encryptor) Decrypt(msg string) (string, error) { + // Decode the base64 string + decMe, err := b64dec(msg) + if err != nil { + panic(err) + } + + md, err := openpgp.ReadMessage(decMe, openpgp.EntityList([]*openpgp.Entity{e.entity}), nil, nil) + if err != nil { + return "", err + } + + plaintext, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + return "", err + } + + return string(plaintext), nil +} diff --git a/second b/second new file mode 100755 index 0000000..e53d587 --- /dev/null +++ b/second @@ -0,0 +1,156 @@ +package encryptor + +import ( + "bytes" + "encoding/base64" + "fmt" + "io" + "io/ioutil" + + "github.com/jchavannes/go-pgp/pgp" + "golang.org/x/crypto/openpgp" + "golang.org/x/crypto/openpgp/armor" +) + +// Encryptor interface +type Encryptor interface { + Encrypt(string) string + Decrypt() string +} + +type encryptor struct { + entity *openpgp.Entity +} + +type readerWriter struct { + b []byte +} + +func (rw *readerWriter) Write(b []byte) (int, error) { + rw.b = b[:] + return len(b), io.EOF +} + +func (rw *readerWriter) Read(b []byte) (int, error) { + b = rw.b[:] + return len(b), io.EOF +} + +func NewKeyPair() (string, string) { + entity, err := openpgp.NewEntity("a", "b", "c@d.e", nil) + if err != nil { + panic(err) + } + + // Sign all the identities + for _, id := range entity.Identities { + err := id.SelfSignature.SignUserId(id.UserId.Id, entity.PrimaryKey, entity.PrivateKey, nil) + if err != nil { + panic(err) + } + } + + rw := &readerWriter{b: make([]byte, 5000)} + b := make([]byte, 5000) + + priW, err := armor.Encode(rw, openpgp.PrivateKeyType, nil) + if err != io.EOF { + fmt.Println(priW, rw) + panic(err) + } + if priW != nil { + defer priW.Close() + entity.SerializePrivate(priW, nil) + } + rw.Read(b) + pri := string(b) + + pubW, err := armor.Encode(rw, openpgp.PublicKeyType, nil) + if err != io.EOF { + panic(err) + } + rw.Read(b) + pub := string(b) + if pubW != nil { + defer pubW.Close() + entity.Serialize(pubW) + } + fmt.Println(pri, pub) + + return pri, pub +} + +// NewEncryptor function +func NewEncryptor(private, public string) *encryptor { + pubKeyPack, err := pgp.GetPublicKeyPacket([]byte(public)) + if err != nil { + panic(err) + } + priKeyPack, err := pgp.GetPrivateKeyPacket([]byte(private)) + if err != nil { + panic(err) + } + entity, err := openpgp.NewEntity("", "", "", nil) + entity.PrimaryKey = pubKeyPack + entity.PrivateKey = priKeyPack + return &encryptor{ + entity: entity, + } +} + +func b64enc(msg io.Reader) (string, error) { + bytes, err := ioutil.ReadAll(msg) + if err != nil { + return "", err + } + return base64.StdEncoding.EncodeToString(bytes), nil +} + +func b64dec(msg string) (io.Reader, error) { + decMe, err := base64.StdEncoding.DecodeString(msg) + if err != nil { + return nil, err + } + return bytes.NewBuffer(decMe), nil +} + +// Encrypt function +func (e *encryptor) Encrypt(msg string) (string, error) { + // encrypt string + buf := new(bytes.Buffer) + w, err := openpgp.Encrypt(buf, []*openpgp.Entity{e.entity}, nil, nil, nil) + if err != nil { + return "", err + } + _, err = w.Write([]byte(msg)) + if err != nil { + return "", err + } + err = w.Close() + if err != nil { + return "", err + } + // Encode to base64 + return b64enc(buf) +} + +// Decrypt function +func (e *encryptor) Decrypt(msg string) (string, error) { + // Decode the base64 string + decMe, err := b64dec(msg) + if err != nil { + panic(err) + } + + md, err := openpgp.ReadMessage(decMe, openpgp.EntityList([]*openpgp.Entity{e.entity}), nil, nil) + if err != nil { + return "", err + } + + plaintext, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + return "", err + } + + return string(plaintext), nil +}