github.com/richardwilkes/toolbox@v1.121.0/xcrypto/stream.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package xcrypto 11 12 import ( 13 "crypto/aes" 14 "crypto/cipher" 15 "crypto/rand" 16 "crypto/rsa" 17 "crypto/sha256" 18 "io" 19 20 "github.com/richardwilkes/toolbox/errs" 21 ) 22 23 // EncryptStreamWithPublicKey copies 'in' to 'out', encrypting the bytes along the way. Note that the output stream will 24 // be larger than the input stream by aes.BlockSize + publicKey.Size() bytes. 25 func EncryptStreamWithPublicKey(in io.Reader, out io.Writer, publicKey *rsa.PublicKey) error { 26 iv := make([]byte, aes.BlockSize) 27 if _, err := io.ReadFull(rand.Reader, iv); err != nil { 28 return errs.Wrap(err) 29 } 30 encryptionKey := make([]byte, 32) // aes256 31 if _, err := io.ReadFull(rand.Reader, encryptionKey); err != nil { 32 return errs.Wrap(err) 33 } 34 encryptedEncryptionKey, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, encryptionKey, nil) 35 if err != nil { 36 return errs.Wrap(err) 37 } 38 block, err := aes.NewCipher(encryptionKey) 39 if err != nil { 40 return errs.Wrap(err) 41 } 42 if _, err = out.Write(encryptedEncryptionKey); err != nil { 43 return errs.Wrap(err) 44 } 45 if _, err = out.Write(iv); err != nil { 46 return errs.Wrap(err) 47 } 48 if _, err = io.Copy(&cipher.StreamWriter{ 49 S: cipher.NewCFBEncrypter(block, iv), 50 W: out, 51 }, in); err != nil { 52 return errs.Wrap(err) 53 } 54 return nil 55 } 56 57 // DecryptStreamWithPrivateKey copies 'in' to 'out', decrypting the bytes along the way. Note that the output stream 58 // will be smaller than the input stream by aes.BlockSize + publicKey.Size() bytes. 59 func DecryptStreamWithPrivateKey(in io.Reader, out io.Writer, privateKey *rsa.PrivateKey) error { 60 encryptedEncryptionKey := make([]byte, privateKey.PublicKey.Size()) 61 if _, err := in.Read(encryptedEncryptionKey); err != nil { 62 return errs.Wrap(err) 63 } 64 iv := make([]byte, aes.BlockSize) 65 if _, err := in.Read(iv); err != nil { 66 return errs.Wrap(err) 67 } 68 encryptionKey, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, encryptedEncryptionKey, nil) 69 if err != nil { 70 return errs.Wrap(err) 71 } 72 block, err := aes.NewCipher(encryptionKey) 73 if err != nil { 74 return errs.Wrap(err) 75 } 76 if _, err = io.Copy(out, &cipher.StreamReader{ 77 S: cipher.NewCFBDecrypter(block, iv), 78 R: in, 79 }); err != nil { 80 return errs.Wrap(err) 81 } 82 return nil 83 }