github.com/lino-network/lino@v0.6.11/client/encrypt/encrypt.go (about) 1 package encrypt 2 3 import ( 4 "crypto/aes" 5 "crypto/cipher" 6 "crypto/rand" 7 "crypto/sha256" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "os" 12 13 "golang.org/x/crypto/ssh/terminal" 14 ) 15 16 func hashPassword(pw string) []byte { 17 hash := sha256.Sum256([]byte(pw)) 18 return hash[:] 19 } 20 21 func Encrypt(data []byte, password string) ([]byte, error) { 22 block, err := aes.NewCipher(hashPassword(password)) 23 if err != nil { 24 return nil, err 25 } 26 gcm, err := cipher.NewGCM(block) 27 if err != nil { 28 return nil, err 29 } 30 nonce := make([]byte, gcm.NonceSize()) 31 if _, err = io.ReadFull(rand.Reader, nonce); err != nil { 32 return nil, err 33 } 34 cipher := gcm.Seal(nonce, nonce, data, nil) 35 return cipher, nil 36 } 37 38 func Decrypt(data []byte, password string) ([]byte, error) { 39 block, err := aes.NewCipher(hashPassword(password)) 40 if err != nil { 41 return nil, err 42 } 43 gcm, err := cipher.NewGCM(block) 44 if err != nil { 45 return nil, err 46 } 47 nonceSize := gcm.NonceSize() 48 nonce, ciphertext := data[:nonceSize], data[nonceSize:] 49 return gcm.Open(nil, nonce, ciphertext, nil) 50 } 51 52 func EncryptToFile(filename string, data []byte, password string) error { 53 cipher, err := Encrypt(data, password) 54 if err != nil { 55 return err 56 } 57 58 f, err := os.Create(filename) 59 if err != nil { 60 return err 61 } 62 defer f.Close() 63 64 _, err = f.Write(cipher) 65 if err != nil { 66 return err 67 } 68 return f.Sync() 69 } 70 71 func DecryptFromFile(filename string, password string) ([]byte, error) { 72 data, err := ioutil.ReadFile(filename) 73 if err != nil { 74 return nil, err 75 } 76 return Decrypt(data, password) 77 } 78 79 func DecryptByStdin(filename string) ([]byte, error) { 80 fmt.Printf("Password of %s: ", filename) 81 pw, err := terminal.ReadPassword(0) 82 if err != nil { 83 return nil, err 84 } 85 fmt.Printf("\n") 86 return DecryptFromFile(filename, string(pw)) 87 }