github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/chat/attachments/crypt.go (about) 1 package attachments 2 3 import ( 4 "crypto/rand" 5 "errors" 6 "io" 7 8 "github.com/keybase/client/go/chat/signencrypt" 9 "github.com/keybase/client/go/kbcrypto" 10 "github.com/keybase/client/go/libkb" 11 "github.com/keybase/go-crypto/ed25519" 12 ) 13 14 type Encrypter interface { 15 // EncryptedLen returns the number of bytes that the ciphertext of 16 // size plaintext bytes will be. 17 EncryptedLen(size int) int 18 19 // Encrypt takes a plaintext reader and returns a ciphertext reader. 20 // It generates new keys every time it is called and uses a 21 // constant nonce. 22 Encrypt(plaintext io.Reader) (ciphertext io.Reader, err error) 23 24 // EncryptWithNonce takes a plaintext reader and returns a ciphertext reader. 25 // It generates new keys every time it is called and uses 26 // the provided nonce. 27 EncryptWithNonce(plaintext io.Reader, nonce signencrypt.Nonce) (ciphertext io.Reader, err error) 28 29 // EncryptResume takes a plaintext reader and a set of keys. It 30 // returns a ciphertext reader. It *does not* generate new keys 31 // but uses the parameter keys. These keys should *only* be used 32 // to encrypt the same plaintext as a previous attempt. 33 EncryptResume(r io.Reader, nonce signencrypt.Nonce, encKey signencrypt.SecretboxKey, signKey signencrypt.SignKey, verifyKey signencrypt.VerifyKey) (io.Reader, error) 34 35 // EncryptKey returns the ephemeral key that was used during the 36 // last invocation of Encrypt. 37 EncryptKey() []byte 38 39 // VerifyKey returns the public portion of the signing key used during 40 // the last invocation of Encrypt. It can be used for signature 41 // verification. 42 VerifyKey() []byte 43 } 44 45 type Decrypter interface { 46 // Decrypt takes a ciphertext reader, encryption and verify keys. 47 // It returns a plaintext reader. It uses the constant nonce. 48 Decrypt(ciphertext io.Reader, encKey, verifyKey []byte) (plaintext io.Reader) 49 50 // DecryptWithNonce takes a ciphertext reader, nonce, encryption and verify keys. 51 // It returns a plaintext reader. 52 DecryptWithNonce(ciphertext io.Reader, nonce signencrypt.Nonce, encKey, verifyKey []byte) (plaintext io.Reader) 53 } 54 55 // The ASCII bytes "kbchatattachment". 56 var nonceConst signencrypt.Nonce = &[16]byte{0x6b, 0x62, 0x63, 0x68, 0x61, 0x74, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74} 57 58 type SignEncrypter struct { 59 encKey signencrypt.SecretboxKey 60 signKey signencrypt.SignKey 61 verifyKey signencrypt.VerifyKey 62 } 63 64 func NewSignEncrypter() *SignEncrypter { 65 return &SignEncrypter{} 66 } 67 68 func (s *SignEncrypter) EncryptedLen(size int64) int64 { 69 return signencrypt.GetSealedSize(size) 70 } 71 72 func (s *SignEncrypter) Encrypt(r io.Reader) (io.Reader, error) { 73 // It is *very* important that Encrypt calls makeKeys() to make 74 // new keys every time it runs. The keys it uses cannot be reused 75 // since we are using a constant nonce. 76 if err := s.makeKeys(); err != nil { 77 return nil, err 78 } 79 return signencrypt.NewEncodingReader(s.encKey, s.signKey, kbcrypto.SignaturePrefixChatAttachment, nonceConst, r), nil 80 } 81 82 func (s *SignEncrypter) EncryptWithNonce(r io.Reader, nonce signencrypt.Nonce) (io.Reader, error) { 83 if err := s.makeKeys(); err != nil { 84 return nil, err 85 } 86 return signencrypt.NewEncodingReader(s.encKey, s.signKey, kbcrypto.SignaturePrefixChatAttachment, nonce, r), nil 87 } 88 89 // EncryptResume is used to create a SignEncrypter to resume an interrupted attachment upload. 90 // It is *very* important that the keys passed in are not used to encrypt different plaintext 91 // than their original usage. 92 func (s *SignEncrypter) EncryptResume(r io.Reader, nonce signencrypt.Nonce, encKey signencrypt.SecretboxKey, signKey signencrypt.SignKey, verifyKey signencrypt.VerifyKey) (io.Reader, error) { 93 s.encKey = encKey 94 s.signKey = signKey 95 s.verifyKey = verifyKey 96 return signencrypt.NewEncodingReader(s.encKey, s.signKey, kbcrypto.SignaturePrefixChatAttachment, nonce, r), nil 97 } 98 99 func (s *SignEncrypter) EncryptKey() []byte { 100 return (*s.encKey)[:] 101 } 102 103 func (s *SignEncrypter) SignKey() []byte { 104 return (*s.signKey)[:] 105 } 106 107 func (s *SignEncrypter) VerifyKey() []byte { 108 return (*s.verifyKey)[:] 109 } 110 111 func (s *SignEncrypter) makeKeys() error { 112 var encKey [signencrypt.SecretboxKeySize]byte 113 n, err := rand.Read(encKey[:]) 114 if err != nil { 115 return err 116 } 117 if n != signencrypt.SecretboxKeySize { 118 return errors.New("failed to rand.Read the correct number of bytes") 119 } 120 121 sign, err := libkb.GenerateNaclSigningKeyPair() 122 if err != nil { 123 return err 124 } 125 126 var signKey [ed25519.PrivateKeySize]byte 127 copy(signKey[:], (*sign.Private)[:]) 128 var verifyKey [ed25519.PublicKeySize]byte 129 copy(verifyKey[:], sign.Public[:]) 130 131 s.encKey = &encKey 132 s.signKey = &signKey 133 s.verifyKey = &verifyKey 134 135 return nil 136 } 137 138 type SignDecrypter struct{} 139 140 func NewSignDecrypter() *SignDecrypter { 141 return &SignDecrypter{} 142 } 143 144 func (s *SignDecrypter) Decrypt(r io.Reader, encKey, verifyKey []byte) io.Reader { 145 var xencKey [signencrypt.SecretboxKeySize]byte 146 copy(xencKey[:], encKey) 147 var xverifyKey [ed25519.PublicKeySize]byte 148 copy(xverifyKey[:], verifyKey) 149 return signencrypt.NewDecodingReader(&xencKey, &xverifyKey, kbcrypto.SignaturePrefixChatAttachment, nonceConst, r) 150 } 151 152 func (s *SignDecrypter) DecryptWithNonce(r io.Reader, nonce signencrypt.Nonce, encKey, verifyKey []byte) (plaintext io.Reader) { 153 var xencKey [signencrypt.SecretboxKeySize]byte 154 copy(xencKey[:], encKey) 155 var xverifyKey [ed25519.PublicKeySize]byte 156 copy(xverifyKey[:], verifyKey) 157 return signencrypt.NewDecodingReader(&xencKey, &xverifyKey, kbcrypto.SignaturePrefixChatAttachment, nonce, r) 158 }