I've just took a look into chachapoly1305 library's source files and I 
found *Seal* and *Open* 
functions: 
https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.14.0:chacha20poly1305/chacha20poly1305_generic.go
 
.

You're right: the 16 bytes are a Poly1305 authentication tag and here is 
how it's generated:


func writeWithPadding(p *poly1305.MAC, b []byte) { 
p.Write(b) 
if rem := len(b) % 16; rem != 0 { 
var buf [16]byte 
padLen := 16 - rem 
p.Write(buf[:padLen]) 
} 
} 
func writeUint64(p *poly1305.MAC, n int) { 
var buf [8]byte 
binary.LittleEndian.PutUint64(buf[:], uint64(n)) 
p.Write(buf[:]) 
}

func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, 
additionalData []byte) []byte { 
ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize) 
ciphertext, tag := out[:len(plaintext)], out[len(plaintext):] 
if alias.InexactOverlap(out, plaintext) { 
panic("chacha20poly1305: invalid buffer overlap") 
} 
var polyKey [32]byte 
s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) 
s.XORKeyStream(polyKey[:], polyKey[:]) 
s.SetCounter(1) // set the counter to 1, skipping 32 bytes 
s.XORKeyStream(ciphertext, plaintext) 
p := poly1305.New(&polyKey) 
writeWithPadding(p, additionalData) 
writeWithPadding(p, ciphertext) 
writeUint64(p, len(additionalData)) 
writeUint64(p, len(plaintext)) 
p.Sum(tag[:0]) 
return ret 
}


Any suggestions about how to replicate the same thing with Crypto++?
On Monday, November 6, 2023 at 11:53:29 PM UTC+1 Lucas Marchetti wrote:

> You're right, pics are not helpful.
> I've also followed the advise about using test vectors instead of messages.
>
> That's a remake of what I need to implement in my application.
>
> *test.cpp*
>
> #include <cryptopp/cryptlib.h>
> #include <cryptopp/chachapoly.h>
> #include <cryptopp/filters.h>
> #include <cryptopp/files.h>
> #include <cryptopp/hex.h>
>
>
> int main(int argc, char* argv[])
> {
>     using namespace CryptoPP;
>
>     const byte pt[] = {
>         
> 0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61,0x6e,0x64,0x20,0x47,0x65,0x6e,0x74,0x6c,
>         
> 0x65,0x6d,0x65,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x6c,0x61,0x73,
>         
> 0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39,0x3a,0x20,0x49,0x66,0x20,0x49,0x20,0x63,
>         
> 0x6f,0x75,0x6c,0x64,0x20,0x6f,0x66,0x66,0x65,0x72,0x20,0x79,0x6f,0x75,0x20,0x6f,
>         
> 0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20,0x74,0x69,0x70,0x20,0x66,0x6f,0x72,0x20,
>         
> 0x74,0x68,0x65,0x20,0x66,0x75,0x74,0x75,0x72,0x65,0x2c,0x20,0x73,0x75,0x6e,0x73,
>         
> 0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f,0x75,0x6c,0x64,0x20,0x62,0x65,0x20,0x69,
>         0x74,0x2e
>     };
>
>     const byte aad[] = {
>         0x50,0x51,0x52,0x53,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7
>     };
>
>     const byte key[] = {
>         
> 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
>         
> 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
>     };
>
>     const byte iv[] = {
>         0x07,0x00,0x00,0x00,                      // Common
>         0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47   // IV
>     };
>
>     byte ct[sizeof(pt)], rt[sizeof(ct)], mac[16];
>
>     ChaCha20Poly1305::Encryption enc;
>     enc.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
>     enc.EncryptAndAuthenticate(ct, mac, sizeof(mac), iv, sizeof(iv), aad, 
> sizeof(aad), (const byte*)pt, sizeof(pt));
>
>     std::cout << "Plain: \n";
>     StringSource((const byte*)pt, sizeof(pt), true, new HexEncoder(new 
> FileSink(std::cout)));
>     std::cout << "\n" << std::endl;
>
>     std::cout << "Cipher: \n";
>     
>     for (int i = 0; i < sizeof(ct); ++i) {
>
>         std::cout << (uint)ct[i] << " ";
>
>     }
>
>     std::cout << std::endl;
>     
>     std::cout << "\nMAC: \n";
>     StringSource(mac, sizeof(mac), true, new HexEncoder(new 
> FileSink(std::cout)));
>     std::cout << "\n" << std::endl;
>
>     ChaCha20Poly1305::Decryption dec;
>     dec.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
>     dec.DecryptAndVerify(rt, mac, sizeof(mac), iv, sizeof(iv), aad, 
> sizeof(aad), ct, sizeof(ct));
>
>     std::cout << "Recover: ";
>
>     StringSource(rt, sizeof(rt), true, new HexEncoder(new 
> FileSink(std::cout)));
>
>     std::cout << std::endl;
>
>     return 0;
> }
>
> *test.go*
>
> package main
>
> import (
> "crypto/cipher"
>
> "fmt"
>
> "golang.org/x/crypto/chacha20poly1305"
> )
>
> // Encryption.
> var (
>
> key []byte
> encryptedMsg []byte
> aead cipher.AEAD
>
> )
>
> func remove(slice []byte, s int) []byte {
>     return append(slice[:s], slice[s+1:]...)
> }
>
> func EncrytionWithChaChaPoly() {
>
> msg := make([]byte, 0)
> msg = append(msg, 
>
>
> 0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61,0x6e,0x64,0x20,0x47,0x65,0x6e,0x74,0x6c,
>         
> 0x65,0x6d,0x65,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x6c,0x61,0x73,
>         
> 0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39,0x3a,0x20,0x49,0x66,0x20,0x49,0x20,0x63,
>         
> 0x6f,0x75,0x6c,0x64,0x20,0x6f,0x66,0x66,0x65,0x72,0x20,0x79,0x6f,0x75,0x20,0x6f,
>         
> 0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20,0x74,0x69,0x70,0x20,0x66,0x6f,0x72,0x20,
>         
> 0x74,0x68,0x65,0x20,0x66,0x75,0x74,0x75,0x72,0x65,0x2c,0x20,0x73,0x75,0x6e,0x73,
>         
> 0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f,0x75,0x6c,0x64,0x20,0x62,0x65,0x20,0x69,
>         0x74,0x2e,
>
> )
>
> // Select a random nonce, and leave capacity for the ciphertext.
> nonce := make([]byte, 0)
> nonce = append(nonce, 0x07,0x00,0x00,0x00,                      // Common
>         0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47)
>
> fmt.Println("Nonce:")
> fmt.Println(nonce)
>
> // Encrypt the message and append the ciphertext to the nonce.
> encryptedMsg = aead.Seal(nonce, nonce, msg, nil)
>
> fmt.Println("\nCipher:")
> fmt.Println(encryptedMsg)
>
> }
>
> // Decryption.
> func DecryptionWithChaChaPoly(){
>
> if len(encryptedMsg) < aead.NonceSize() {
> panic("ciphertext too short")
> }
>
> // Split nonce and ciphertext.
> nonce, ciphertext := encryptedMsg[:aead.NonceSize()], 
> encryptedMsg[aead.NonceSize():]
>
> // Decrypt the message and check it wasn't tampered with.
> plaintext, err := aead.Open(nil, nonce, ciphertext, nil)
> if err != nil {
> panic(err)
> }
>
> fmt.Println("\nRecover:")
> fmt.Printf("%s\n", plaintext)
>
> }
>
> func main(){
>
> var err error
>
> key = make([]byte, 0)
> key = append(key, 
> 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
>           
> 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f)
>
> aead, err = chacha20poly1305.New(key)
> if err != nil {
> panic(err)
> }
>
> EncrytionWithChaChaPoly()
>
> DecryptionWithChaChaPoly()
>
> }
>
> Here you are the output.
> The highlighted text is the same of the Crypto++ output.
>
> [image: Screenshot 2023-11-06 234054.png]
>
> I think the 16 bytes at the end are part of the *Seal* function and 
> corresponds to the *additionalData *parameter as shown in the next pic.
> Maybe the function still do something with a null pointer, so it will 
> append those bytes to the ciphertext anyway.
>
> [image: Screenshot 2023-11-06 234437.png]
>
> Looks like *Seal *is doing something like this: *Nonce *+ *Ciphertext *+ 
> *AdditionalData(?)*
> Any ideas?
> On Sunday, November 5, 2023 at 8:26:27 PM UTC+1 Jeffrey Walton wrote:
>
>> On Sun, Nov 5, 2023 at 4:38 AM Lucas Marchetti <lmarch...@gmail.com> 
>> wrote:
>>
>>> Sorry, seeing now that I've linked the wrong Golang library, here it is: 
>>> https://pkg.go.dev/golang.org/x/crypto/chacha20poly1305
>>>
>>> On Sunday, November 5, 2023 at 10:10:44 AM UTC+1 Lucas Marchetti wrote:
>>>
>>>> I've just made a test encrypting the string "Hello World!" with both 
>>>> client and server functions and these are the results.
>>>>
>>>> [image: Screenshot 2023-11-05 100312.png]
>>>>
>>>> Both green-highlighted bytes corresponds to the input string but, as 
>>>> you can see, there is a different padding that I'm 100% sure is the source 
>>>> of the problem.
>>>>
>>>> On Saturday, November 4, 2023 at 7:39:31 PM UTC+1 Lucas Marchetti wrote:
>>>>
>>>>> Good evening.
>>>>>
>>>>> I'm building a client-server application and I want to implement a 
>>>>> XChaCha20 communication over TCP after performing key exchange.
>>>>>
>>>>> What I'm issuing is a bad decryption output like the one shown in the 
>>>>> pic.
>>>>>
>>>>> [image: Screenshot 2023-11-04 193625.png]
>>>>>
>>>>> I'm currently using crypto++ 8.9 in the client-side and 
>>>>> https://pkg.go.dev/golang.org/x/crypto/chacha20 in the server-side.
>>>>>
>>>>> Is that something related to sealing or authentication implemented in 
>>>>> the Golang library?
>>>>>
>>>>> Functions that I'm using:
>>>>>
>>>>> [image: Screenshot 2023-11-04 193751.png]
>>>>>
>>>>> [image: Screenshot 2023-11-04 193832.png]
>>>>>
>>>>> Thanks in advance.
>>>>>
>>>> If you want help, then you should provide source code and post a link 
>> to a minimal reproducer. Pictures are not helpful.
>>
>> The wiki is full of little working examples. For example, <
>> https://www.cryptopp.com/wiki/XChaCha20> and <
>> https://www.cryptopp.com/wiki/XChaCha20Poly1305>.
>>
>> You should also probably start with test vectors, and then move onto 
>> arbitrary messages once things work with test vectors. Here are the ones 
>> Crypto++ uses for XChaCha: <
>> https://github.com/weidai11/cryptopp/blob/master/TestVectors/chacha.txt>. 
>> And here are the ones for ChaCha20/Poly1305: <
>> https://github.com/weidai11/cryptopp/blob/master/TestVectors/chacha20poly1305.txt#L4669
>> >.
>>
>> I'm just guessing, but the 16-bytes of garbage at the end of the 
>> [encrypted] message may be a Poly1305 authentication tag. But it is just a 
>> guess. The go documentation should tell you what you have.
>>
>> Jeff
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Crypto++ Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to cryptopp-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/cryptopp-users/455def34-d321-4f2c-a297-197b96410d72n%40googlegroups.com.

Reply via email to