Re: Re: XChaCha20 decryption issue.

Lucas Marchetti <[email protected]> Wed, 8 Nov 2023 07:33:11 -0800 (PST)
Newsgroups gmane.comp.encryption.cryptopp
Message-ID <[email protected]>
------=_Part_40205_1235931769.1699457591584
Content-Type: multipart/alternative; 
	boundary="----=_Part_40206_244180868.1699457591584"

------=_Part_40206_244180868.1699457591584
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

And if you're interested about original functions here you are:


func writeWithPadding(p *poly1305.MAC, b []byte) {=20
p.Write(b)=20
if rem :=3D len(b) % 16; rem !=3D 0 {=20
var buf [16]byte=20
padLen :=3D 16 - rem=20
p.Write(buf[:padLen])=20
}=20
}=20
func writeUint64(p *poly1305.MAC, n int) {=20
var buf [8]byte=20
binary.LittleEndian.PutUint64(buf[:], uint64(n))=20
p.Write(buf[:])=20
}=20
func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext,=20
additionalData []byte) []byte {=20
ret, out :=3D sliceForAppend(dst, len(plaintext)+poly1305.TagSize)=20
ciphertext, tag :=3D out[:len(plaintext)], out[len(plaintext):]=20
if alias.InexactOverlap(out, plaintext) {=20
panic("chacha20poly1305: invalid buffer overlap")=20
}=20
var polyKey [32]byte=20
s, _ :=3D chacha20.NewUnauthenticatedCipher(c.key[:], nonce)=20
s.XORKeyStream(polyKey[:], polyKey[:])=20
s.SetCounter(1) // set the counter to 1, skipping 32 bytes=20
s.XORKeyStream(ciphertext, plaintext)=20
p :=3D poly1305.New(&polyKey)=20
writeWithPadding(p, additionalData)=20
writeWithPadding(p, ciphertext)=20
writeUint64(p, len(additionalData))=20
writeUint64(p, len(plaintext))=20
p.Sum(tag[:0])=20
return ret=20
}=20
func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext,=20
additionalData []byte) ([]byte, error) {=20
tag :=3D ciphertext[len(ciphertext)-16:]=20
ciphertext =3D ciphertext[:len(ciphertext)-16]=20
var polyKey [32]byte=20
s, _ :=3D chacha20.NewUnauthenticatedCipher(c.key[:], nonce)=20
s.XORKeyStream(polyKey[:], polyKey[:])=20
s.SetCounter(1) // set the counter to 1, skipping 32 bytes=20
p :=3D poly1305.New(&polyKey)=20
writeWithPadding(p, additionalData)=20
writeWithPadding(p, ciphertext)=20
writeUint64(p, len(additionalData))=20
writeUint64(p, len(ciphertext))=20
ret, out :=3D sliceForAppend(dst, len(ciphertext))=20
if alias.InexactOverlap(out, ciphertext) {=20
panic("chacha20poly1305: invalid buffer overlap")=20
}=20
if !p.Verify(tag) {=20
for i :=3D range out {=20
out[i] =3D 0=20
}=20
return nil, errOpen=20
}=20
s.XORKeyStream(out, ciphertext)=20
return ret, nil=20
}


You can find the source files=20
at https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.14.0:chacha20pol=
y1305/=20
.
The reported functions can be found=20
at https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.14.0:chacha20pol=
y1305/chacha20poly1305_generic.go=20
.
On Wednesday, November 8, 2023 at 4:25:07=E2=80=AFPM UTC+1 Lucas Marchetti =
wrote:

> Hi Jeff, thanks for the reply.
>
> I've deleted the other messages cause I've found the solution by my own.
>
> So, I've tested the whole thing with a test vector as you said and I foun=
d=20
> out, looking to Golang library's source code, that the output given to me=
=20
> was: *Nonce + Ciphertext + MAC*.
> You were right: the last one was actually an authentication tag.
>
> I decided to reimplement manually the *Seal *and *Open* functions=20
> removing the MAC generation and append.
> I think I'm gonna implement it back in a bit: I prefer to go without=20
> authenticated encryption at the moment.
>
> With a custom function I'm now able to remove the Nonce too and get the=
=20
> clear ciphertext that I can finally decrypt using Crypto++.
>
> Here is the source code of the changed functions.
>
> func sliceForAppend(in []byte, n int) (head, tail []byte) {
>
> if total :=3D len(in) + n; cap(in) >=3D total {
>
> head =3D in[:total]
>
> } else {
>
> head =3D make([]byte, total)
> copy(head, in)
>
> }
>
> tail =3D head[len(in):]
> return
>
> }
>
> func sealGeneric(dst, nonce, plaintext []byte) []byte {
>
> ret, out :=3D sliceForAppend(dst, len(plaintext))
> ciphertext, _ :=3D out[:len(plaintext)], out[len(plaintext):]
>
> var polyKey [32]byte
> s, _ :=3D chacha20.NewUnauthenticatedCipher(key[:], nonce)
> s.XORKeyStream(polyKey[:], polyKey[:])
> s.SetCounter(1) // set the counter to 1, skipping 32 bytes
> s.XORKeyStream(ciphertext, plaintext)
>
> return ret
>
> }
>
> func openGeneric(dst, nonce, ciphertext []byte) ([]byte, error) {
>
> var polyKey [32]byte
> s, _ :=3D chacha20.NewUnauthenticatedCipher(key[:], nonce)
> s.XORKeyStream(polyKey[:], polyKey[:])
> s.SetCounter(1) // set the counter to 1, skipping 32 bytes
>
> ret, out :=3D sliceForAppend(dst, len(ciphertext))
>
> s.XORKeyStream(out, ciphertext)
>
> return ret, nil
>
> }
>
> That's how I call encryption and decryption:
>
> func EncrytionWithChaChaPoly() {
>
> msg :=3D make([]byte, 0)
> msg =3D append(msg,
>
>
> 0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61,0x6e,0x64,0x20,0x47,0x65,0x6e,0x7=
4,0x6c,
>        =20
> 0x65,0x6d,0x65,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x6c,0x6=
1,0x73,
>        =20
> 0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39,0x3a,0x20,0x49,0x66,0x20,0x49,0x2=
0,0x63,
>        =20
> 0x6f,0x75,0x6c,0x64,0x20,0x6f,0x66,0x66,0x65,0x72,0x20,0x79,0x6f,0x75,0x2=
0,0x6f,
>        =20
> 0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20,0x74,0x69,0x70,0x20,0x66,0x6f,0x7=
2,0x20,
>        =20
> 0x74,0x68,0x65,0x20,0x66,0x75,0x74,0x75,0x72,0x65,0x2c,0x20,0x73,0x75,0x6=
e,0x73,
>        =20
> 0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f,0x75,0x6c,0x64,0x20,0x62,0x65,0x2=
0,0x69,
>         0x74,0x2e,
>
> )
>
> nonce :=3D make([]byte, 0)
> nonce =3D append(nonce,=20
> 0x07,0x00,0x00,0x00,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x07,0x00,0x0=
0,0x00,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 =3D sealGeneric(nonce, nonce, msg)
>
> fmt.Println("\nCipher:")
> fmt.Println(encryptedMsg)
> fmt.Println(len(encryptedMsg))
>
> }
>
> func DecryptionWithChaChaPoly(){
>
> if len(encryptedMsg) < aead.NonceSize() {
> panic("ciphertext too short")
> }
>
> // Split nonce and ciphertext.
> nonce, ciphertext :=3D encryptedMsg[:aead.NonceSize()],=20
> encryptedMsg[aead.NonceSize():]
>
> // Decrypt the message and check it wasn't tampered with.
> plaintext, err :=3D openGeneric(nil, nonce, ciphertext)
>
> if err !=3D nil {
> panic(err)
> }
>
> fmt.Println("\nRecover:")
> fmt.Printf("%s\n", plaintext)
>
> }
>
> Tell me if I did something wrong.
>
> Thanks in advance.
> On Sunday, November 5, 2023 at 8:26:27=E2=80=AFPM UTC+1 Jeffrey Walton wr=
ote:
>
>> On Sun, Nov 5, 2023 at 4:38=E2=80=AFAM Lucas Marchetti <lmarch...@gmail.=
com>=20
>> wrote:
>>
>>> Sorry, seeing now that I've linked the wrong Golang library, here it is=
:=20
>>> https://pkg.go.dev/golang.org/x/crypto/chacha20poly1305
>>>
>>> On Sunday, November 5, 2023 at 10:10:44=E2=80=AFAM UTC+1 Lucas Marchett=
i wrote:
>>>
>>>> I've just made a test encrypting the string "Hello World!" with both=
=20
>>>> 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=
=20
>>>> you can see, there is a different padding that I'm 100% sure is the so=
urce=20
>>>> of the problem.
>>>>
>>>> On Saturday, November 4, 2023 at 7:39:31=E2=80=AFPM UTC+1 Lucas Marche=
tti wrote:
>>>>
>>>>> Good evening.
>>>>>
>>>>> I'm building a client-server application and I want to implement a=20
>>>>> XChaCha20 communication over TCP after performing key exchange.
>>>>>
>>>>> What I'm issuing is a bad decryption output like the one shown in the=
=20
>>>>> pic.
>>>>>
>>>>> [image: Screenshot 2023-11-04 193625.png]
>>>>>
>>>>> I'm currently using crypto++ 8.9 in the client-side and=20
>>>>> https://pkg.go.dev/golang.org/x/crypto/chacha20 in the server-side.
>>>>>
>>>>> Is that something related to sealing or authentication implemented in=
=20
>>>>> 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=
=20
>> 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=20
>> arbitrary messages once things work with test vectors. Here are the ones=
=20
>> Crypto++ uses for XChaCha: <
>> https://github.com/weidai11/cryptopp/blob/master/TestVectors/chacha.txt>=
.=20
>> And here are the ones for ChaCha20/Poly1305: <
>> https://github.com/weidai11/cryptopp/blob/master/TestVectors/chacha20pol=
y1305.txt#L4669
>> >.
>>
>> I'm just guessing, but the 16-bytes of garbage at the end of the=20
>> [encrypted] message may be a Poly1305 authentication tag. But it is just=
 a=20
>> guess. The go documentation should tell you what you have.
>>
>> Jeff
>>
>

--=20
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 e=
mail to [email protected].
To view this discussion on the web visit https://groups.google.com/d/msgid/=
cryptopp-users/bbe5ba70-1d8b-4bdd-bfc0-4c176e420da2n%40googlegroups.com.

------=_Part_40206_244180868.1699457591584
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

And if you're interested about original functions here you are:<div><br /><=
div><br /></div><div><div style=3D"margin: 0px; padding: 0px; box-sizing: b=
order-box; color: rgb(0, 0, 0); font-family: monospace; font-size: medium; =
white-space: pre;"><span style=3D"margin: 0px; padding: 0px; box-sizing: bo=
rder-box; color: rgb(119, 0, 136);">func</span> writeWithPadding(p *poly130=
5.MAC, b []byte) {
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	p.Write(b)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(119, 0, 136);">if</span> rem :=3D len(b) % <span style=3D"margin: 0p=
x; padding: 0px; box-sizing: border-box; color: rgb(17, 102, 68);">16</span=
>; rem !=3D <span style=3D"margin: 0px; padding: 0px; box-sizing: border-bo=
x; color: rgb(17, 102, 68);">0</span> {
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">		<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; col=
or: rgb(119, 0, 136);">var</span> buf [<span style=3D"margin: 0px; padding:=
 0px; box-sizing: border-box; color: rgb(17, 102, 68);">16</span>]byte
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">		padLen :=3D <span style=3D"margin: 0px; padding: 0px; box-sizing: bor=
der-box; color: rgb(17, 102, 68);">16</span> - rem
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">		p.Write(buf[:padLen])
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	}
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">}
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;"><span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; color=
: rgb(119, 0, 136);">func</span> writeUint64(p *poly1305.MAC, n int) {
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(119, 0, 136);">var</span> buf [<span style=3D"margin: 0px; padding: =
0px; box-sizing: border-box; color: rgb(17, 102, 68);">8</span>]byte
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	binary.LittleEndian.PutUint64(buf[:], uint64(n))
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	p.Write(buf[:])
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">}
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;"><span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; color=
: rgb(119, 0, 136);">func</span> (c *chacha20poly1305) sealGeneric(dst, non=
ce, plaintext, additionalData []byte) []byte {
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	ret, out :=3D sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	ciphertext, tag :=3D out[:len(plaintext)], out[len(plaintext):]
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(119, 0, 136);">if</span> alias.InexactOverlap(out, plaintext) {
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">		panic(<span style=3D"margin: 0px; padding: 0px; box-sizing: border-bo=
x; color: rgb(19, 115, 51);">"chacha20poly1305: invalid buffer overlap"</sp=
an>)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	}
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(119, 0, 136);">var</span> polyKey [<span style=3D"margin: 0px; paddi=
ng: 0px; box-sizing: border-box; color: rgb(17, 102, 68);">32</span>]byte
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	s, _ :=3D chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	s.XORKeyStream(polyKey[:], polyKey[:])
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	s.SetCounter(<span style=3D"margin: 0px; padding: 0px; box-sizing: bor=
der-box; color: rgb(17, 102, 68);">1</span>) <span style=3D"margin: 0px; pa=
dding: 0px; box-sizing: border-box; color: rgb(136, 0, 0);">// set the coun=
ter to 1, skipping 32 bytes</span>
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	s.XORKeyStream(ciphertext, plaintext)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	p :=3D poly1305.New(&amp;polyKey)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	writeWithPadding(p, additionalData)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	writeWithPadding(p, ciphertext)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	writeUint64(p, len(additionalData))
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	writeUint64(p, len(plaintext))
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	p.Sum(tag[:<span style=3D"margin: 0px; padding: 0px; box-sizing: borde=
r-box; color: rgb(17, 102, 68);">0</span>])
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(119, 0, 136);">return</span> ret
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">}
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;"><span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; color=
: rgb(119, 0, 136);">func</span> (c *chacha20poly1305) openGeneric(dst, non=
ce, ciphertext, additionalData []byte) ([]byte, error) {
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	tag :=3D ciphertext[len(ciphertext)-<span style=3D"margin: 0px; paddin=
g: 0px; box-sizing: border-box; color: rgb(17, 102, 68);">16</span>:]
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	ciphertext =3D ciphertext[:len(ciphertext)-<span style=3D"margin: 0px;=
 padding: 0px; box-sizing: border-box; color: rgb(17, 102, 68);">16</span>]
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(119, 0, 136);">var</span> polyKey [<span style=3D"margin: 0px; paddi=
ng: 0px; box-sizing: border-box; color: rgb(17, 102, 68);">32</span>]byte
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	s, _ :=3D chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	s.XORKeyStream(polyKey[:], polyKey[:])
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	s.SetCounter(<span style=3D"margin: 0px; padding: 0px; box-sizing: bor=
der-box; color: rgb(17, 102, 68);">1</span>) <span style=3D"margin: 0px; pa=
dding: 0px; box-sizing: border-box; color: rgb(136, 0, 0);">// set the coun=
ter to 1, skipping 32 bytes</span>
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	p :=3D poly1305.New(&amp;polyKey)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	writeWithPadding(p, additionalData)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	writeWithPadding(p, ciphertext)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	writeUint64(p, len(additionalData))
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	writeUint64(p, len(ciphertext))
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	ret, out :=3D sliceForAppend(dst, len(ciphertext))
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(119, 0, 136);">if</span> alias.InexactOverlap(out, ciphertext) {
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">		panic(<span style=3D"margin: 0px; padding: 0px; box-sizing: border-bo=
x; color: rgb(19, 115, 51);">"chacha20poly1305: invalid buffer overlap"</sp=
an>)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	}
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(119, 0, 136);">if</span> !p.Verify(tag) {
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">		<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; col=
or: rgb(119, 0, 136);">for</span> i :=3D <span style=3D"margin: 0px; paddin=
g: 0px; box-sizing: border-box; color: rgb(119, 0, 136);">range</span> out =
{
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">			out[i] =3D <span style=3D"margin: 0px; padding: 0px; box-sizing: bor=
der-box; color: rgb(17, 102, 68);">0</span>
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">		}
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">		<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; col=
or: rgb(119, 0, 136);">return</span> nil, errOpen
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	}
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	s.XORKeyStream(out, ciphertext)
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">	<span style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(119, 0, 136);">return</span> ret, nil
</div><div style=3D"margin: 0px; padding: 0px; box-sizing: border-box; colo=
r: rgb(0, 0, 0); font-family: monospace; font-size: medium; white-space: pr=
e;">}</div><br /></div></div><div><br /></div><div>You can find the source =
files at=C2=A0https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.14.0:=
chacha20poly1305/ .</div><div>The reported functions can be found at=C2=A0h=
ttps://cs.opensource.google/go/x/crypto/+/refs/tags/v0.14.0:chacha20poly130=
5/chacha20poly1305_generic.go .</div><div class=3D"gmail_quote"><div dir=3D=
"auto" class=3D"gmail_attr">On Wednesday, November 8, 2023 at 4:25:07=E2=80=
=AFPM UTC+1 Lucas Marchetti wrote:<br/></div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0 0 0 0.8ex; border-left: 1px solid rgb(204, 204, 204)=
; padding-left: 1ex;">Hi Jeff, thanks for the reply.<br><br>I&#39;ve delete=
d the other messages cause I&#39;ve found the solution by my own.<div><br><=
/div><div>So, I&#39;ve tested the whole thing with a test vector as you sai=
d and I found out, looking to Golang library&#39;s source code, that the ou=
tput given to me was: <b>Nonce + Ciphertext + MAC</b>.</div><div>You were r=
ight: the last one was actually an authentication tag.</div><div><br></div>=
<div>I decided to reimplement manually the <i>Seal </i>and <i>Open</i>=C2=
=A0functions removing the MAC generation and append.</div><div>I think I&#3=
9;m gonna implement it back in a bit: I prefer to go without authenticated =
encryption at the moment.</div><div><br></div><div>With a custom function I=
&#39;m now able to remove the Nonce too and get the clear ciphertext that I=
 can finally decrypt using Crypto++.</div><div><br></div><div>Here is the s=
ource code of the changed functions.</div><div><br></div><div><font color=
=3D"#008000">func sliceForAppend(in []byte, n int) (head, tail []byte) {<br=
><br><span style=3D"white-space:pre">	</span>if total :=3D len(in) + n; cap=
(in) &gt;=3D total {<br><br><span style=3D"white-space:pre">		</span>head =
=3D in[:total]<br><br><span style=3D"white-space:pre">	</span>} else {<br><=
br><span style=3D"white-space:pre">		</span>head =3D make([]byte, total)<br=
><span style=3D"white-space:pre">		</span>copy(head, in)<br><br><span style=
=3D"white-space:pre">	</span>}<br><br><span style=3D"white-space:pre">	</sp=
an>tail =3D head[len(in):]<br><span style=3D"white-space:pre">	</span>retur=
n<br><br>}</font><br></div><div><br></div><div><font color=3D"#008000">func=
 sealGeneric(dst, nonce, plaintext []byte) []byte {<br><br><span style=3D"w=
hite-space:pre">	</span>ret, out :=3D sliceForAppend(dst, len(plaintext))<b=
r><span style=3D"white-space:pre">	</span>ciphertext, _ :=3D out[:len(plain=
text)], out[len(plaintext):]<br><br><span style=3D"white-space:pre">	</span=
>var polyKey [32]byte<br><span style=3D"white-space:pre">	</span>s, _ :=3D =
chacha20.NewUnauthenticatedCipher(key[:], nonce)<br><span style=3D"white-sp=
ace:pre">	</span>s.XORKeyStream(polyKey[:], polyKey[:])<br><span style=3D"w=
hite-space:pre">	</span>s.SetCounter(1) // set the counter to 1, skipping 3=
2 bytes<br><span style=3D"white-space:pre">	</span>s.XORKeyStream(ciphertex=
t, plaintext)<br><br><span style=3D"white-space:pre">	</span>return ret<br>=
<br>}<br><br>func openGeneric(dst, nonce, ciphertext []byte) ([]byte, error=
) {<br><br><span style=3D"white-space:pre">	</span>var polyKey [32]byte<br>=
<span style=3D"white-space:pre">	</span>s, _ :=3D chacha20.NewUnauthenticat=
edCipher(key[:], nonce)<br><span style=3D"white-space:pre">	</span>s.XORKey=
Stream(polyKey[:], polyKey[:])<br><span style=3D"white-space:pre">	</span>s=
.SetCounter(1) // set the counter to 1, skipping 32 bytes<br><br><span styl=
e=3D"white-space:pre">	</span>ret, out :=3D sliceForAppend(dst, len(ciphert=
ext))<br><br><span style=3D"white-space:pre">	</span>s.XORKeyStream(out, ci=
phertext)<br><br><span style=3D"white-space:pre">	</span>return ret, nil<br=
><br>}<br></font></div><div><br></div><div>That&#39;s how I call encryption=
 and decryption:</div><div><br></div><div><font color=3D"#008000">func Encr=
ytionWithChaChaPoly() {<br><br><span style=3D"white-space:pre">	</span>msg =
:=3D make([]byte, 0)<br><span style=3D"white-space:pre">	</span>msg =3D app=
end(msg,<br><span style=3D"white-space:pre">		</span><br><span style=3D"whi=
te-space:pre">		</span>0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61,0x6e,0x64,0x=
20,0x47,0x65,0x6e,0x74,0x6c,<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x65,0x6d,0x65,=
0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x6c,0x61,0x73,<br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39,0x3a,0x20,0x4=
9,0x66,0x20,0x49,0x20,0x63,<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x6f,0x75,0x6c,0=
x64,0x20,0x6f,0x66,0x66,0x65,0x72,0x20,0x79,0x6f,0x75,0x20,0x6f,<br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20,0x74,0x69,0x70=
,0x20,0x66,0x6f,0x72,0x20,<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x74,0x68,0x65,0x=
20,0x66,0x75,0x74,0x75,0x72,0x65,0x2c,0x20,0x73,0x75,0x6e,0x73,<br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f,0x75,0x6c,0x64=
,0x20,0x62,0x65,0x20,0x69,<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x74,0x2e,<br><sp=
an style=3D"white-space:pre">	</span><br><span style=3D"white-space:pre">	<=
/span>)<br><br><span style=3D"white-space:pre">	</span>nonce :=3D make([]by=
te, 0)<br><span style=3D"white-space:pre">	</span>nonce =3D append(nonce, 0=
x07,0x00,0x00,0x00,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x07,0x00,0x00,0=
x00,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47)<br><br><span style=3D"white-sp=
ace:pre">	</span>fmt.Println(&quot;Nonce:&quot;)<br><span style=3D"white-sp=
ace:pre">	</span>fmt.Println(nonce)<br><br><span style=3D"white-space:pre">=
	</span>// Encrypt the message and append the ciphertext to the nonce.<br><=
span style=3D"white-space:pre">	</span>encryptedMsg =3D sealGeneric(nonce, =
nonce, msg)<br><br><span style=3D"white-space:pre">	</span>fmt.Println(&quo=
t;\nCipher:&quot;)<br><span style=3D"white-space:pre">	</span>fmt.Println(e=
ncryptedMsg)<br><span style=3D"white-space:pre">	</span>fmt.Println(len(enc=
ryptedMsg))<br><br>}<br><br>func DecryptionWithChaChaPoly(){<br><br><span s=
tyle=3D"white-space:pre">	</span>if len(encryptedMsg) &lt; aead.NonceSize()=
 {<br><span style=3D"white-space:pre">		</span>panic(&quot;ciphertext too s=
hort&quot;)<br><span style=3D"white-space:pre">	</span>}<br><br><span style=
=3D"white-space:pre">	</span>// Split nonce and ciphertext.<br><span style=
=3D"white-space:pre">	</span>nonce, ciphertext :=3D encryptedMsg[:aead.Nonc=
eSize()], encryptedMsg[aead.NonceSize():]<br><br><span style=3D"white-space=
:pre">	</span>// Decrypt the message and check it wasn&#39;t tampered with.=
<br><span style=3D"white-space:pre">	</span>plaintext, err :=3D openGeneric=
(nil, nonce, ciphertext)<br><br><span style=3D"white-space:pre">	</span>if =
err !=3D nil {<br><span style=3D"white-space:pre">		</span>panic(err)<br><s=
pan style=3D"white-space:pre">	</span>}<br><br><span style=3D"white-space:p=
re">	</span>fmt.Println(&quot;\nRecover:&quot;)<br><span style=3D"white-spa=
ce:pre">	</span>fmt.Printf(&quot;%s\n&quot;, plaintext)<br><br>}</font><br>=
</div><div><br></div><div>Tell me if I did something wrong.<br></div><div><=
br></div><div>Thanks in advance.</div><div class=3D"gmail_quote"><div dir=
=3D"auto" class=3D"gmail_attr">On Sunday, November 5, 2023 at 8:26:27=E2=80=
=AFPM UTC+1 Jeffrey Walton wrote:<br></div><blockquote class=3D"gmail_quote=
" style=3D"margin:0 0 0 0.8ex;border-left:1px solid rgb(204,204,204);paddin=
g-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_quote"><div dir=3D"ltr" cl=
ass=3D"gmail_attr">On Sun, Nov 5, 2023 at 4:38=E2=80=AFAM Lucas Marchetti &=
lt;<a rel=3D"nofollow">[email protected]</a>&gt; wrote:<br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px=
 solid rgb(204,204,204);padding-left:1ex">Sorry, seeing now that I&#39;ve l=
inked the wrong Golang library, here it is:=C2=A0<a href=3D"https://pkg.go.=
dev/golang.org/x/crypto/chacha20poly1305" rel=3D"nofollow" target=3D"_blank=
" data-saferedirecturl=3D"https://www.google.com/url?hl=3Den&amp;q=3Dhttps:=
//pkg.go.dev/golang.org/x/crypto/chacha20poly1305&amp;source=3Dgmail&amp;us=
t=3D1699543509329000&amp;usg=3DAOvVaw0QEh6Tf-9Lf9JzbMSlkdUc">https://pkg.go=
.dev/golang.org/x/crypto/chacha20poly1305</a><br><br><div class=3D"gmail_qu=
ote"><div dir=3D"auto" class=3D"gmail_attr">On Sunday, November 5, 2023 at =
10:10:44=E2=80=AFAM UTC+1 Lucas Marchetti wrote:<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rg=
b(204,204,204);padding-left:1ex">I&#39;ve just made a test encrypting the s=
tring &quot;Hello World!&quot; with both client and server functions and th=
ese are the results.<div><br></div><div><img alt=3D"Screenshot 2023-11-05 1=
00312.png" width=3D"726px" height=3D"111px" src=3D"https://groups.google.co=
m/group/cryptopp-users/attach/5b1bbc5faec59/Screenshot%202023-11-05%2010031=
2.png?part=3D0.1&amp;view=3D1"></div><div><br></div><div>Both green-highlig=
hted bytes corresponds to the input string but, as you can see, there is a =
different padding that I&#39;m 100% sure is the source of the problem.<br><=
br></div><div class=3D"gmail_quote"><div dir=3D"auto" class=3D"gmail_attr">=
On Saturday, November 4, 2023 at 7:39:31=E2=80=AFPM UTC+1 Lucas Marchetti w=
rote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Good eveni=
ng.<br><br>I&#39;m building a client-server application and I want to imple=
ment a XChaCha20 communication over TCP after performing key exchange.<br><=
br>What I&#39;m issuing is a bad decryption output like the one shown in th=
e pic.<br><br><img alt=3D"Screenshot 2023-11-04 193625.png" width=3D"266px"=
 height=3D"19px" src=3D"https://groups.google.com/group/cryptopp-users/atta=
ch/58230e8ec9c5a/Screenshot%202023-11-04%20193625.png?part=3D0.1&amp;view=
=3D1"><br><div><br></div><div>I&#39;m currently using crypto++ 8.9 in the c=
lient-side and=C2=A0<a href=3D"https://pkg.go.dev/golang.org/x/crypto/chach=
a20" rel=3D"nofollow" target=3D"_blank" data-saferedirecturl=3D"https://www=
.google.com/url?hl=3Den&amp;q=3Dhttps://pkg.go.dev/golang.org/x/crypto/chac=
ha20&amp;source=3Dgmail&amp;ust=3D1699543509329000&amp;usg=3DAOvVaw2ExdSbjW=
314IZ4qBXHUgVy">https://pkg.go.dev/golang.org/x/crypto/chacha20</a> in the =
server-side.<div><br></div><div>Is that something related to sealing or aut=
hentication implemented in the Golang library?</div></div><div><br></div><d=
iv>Functions that I&#39;m using:</div><div><br></div><div><img alt=3D"Scree=
nshot 2023-11-04 193751.png" width=3D"534px" height=3D"197px" src=3D"https:=
//groups.google.com/group/cryptopp-users/attach/58230e8ec9c5a/Screenshot%20=
2023-11-04%20193751.png?part=3D0.3&amp;view=3D1"><br></div><div><br></div><=
div><img alt=3D"Screenshot 2023-11-04 193832.png" width=3D"534px" height=3D=
"197px" src=3D"https://groups.google.com/group/cryptopp-users/attach/58230e=
8ec9c5a/Screenshot%202023-11-04%20193832.png?part=3D0.2&amp;view=3D1"><br><=
/div><div><br></div><div>Thanks in advance.</div></blockquote></div></block=
quote></div>

<p></p></blockquote></div></div><div dir=3D"ltr"><div class=3D"gmail_quote"=
><div>If you want help, then you should provide source code and post a link=
 to a minimal reproducer. Pictures are not helpful.</div><div><br></div><di=
v>The wiki is full of little working examples. For example, &lt;<a href=3D"=
https://www.cryptopp.com/wiki/XChaCha20" rel=3D"nofollow" target=3D"_blank"=
 data-saferedirecturl=3D"https://www.google.com/url?hl=3Den&amp;q=3Dhttps:/=
/www.cryptopp.com/wiki/XChaCha20&amp;source=3Dgmail&amp;ust=3D1699543509329=
000&amp;usg=3DAOvVaw1AN0TIBiiJOLvIXaCkDX-z">https://www.cryptopp.com/wiki/X=
ChaCha20</a>&gt; and &lt;<a href=3D"https://www.cryptopp.com/wiki/XChaCha20=
Poly1305" rel=3D"nofollow" target=3D"_blank" data-saferedirecturl=3D"https:=
//www.google.com/url?hl=3Den&amp;q=3Dhttps://www.cryptopp.com/wiki/XChaCha2=
0Poly1305&amp;source=3Dgmail&amp;ust=3D1699543509329000&amp;usg=3DAOvVaw1De=
kq1j3teTnDL376jp7aj">https://www.cryptopp.com/wiki/XChaCha20Poly1305</a>&gt=
;.</div><div><br></div><div>You should also probably start with test vector=
s, and then move onto arbitrary messages once things work with test vectors=
. Here are the ones Crypto++ uses for XChaCha: &lt;<a href=3D"https://githu=
b.com/weidai11/cryptopp/blob/master/TestVectors/chacha.txt" rel=3D"nofollow=
" target=3D"_blank" data-saferedirecturl=3D"https://www.google.com/url?hl=
=3Den&amp;q=3Dhttps://github.com/weidai11/cryptopp/blob/master/TestVectors/=
chacha.txt&amp;source=3Dgmail&amp;ust=3D1699543509329000&amp;usg=3DAOvVaw2v=
FDndbwa3-T2G0__5Z4G2">https://github.com/weidai11/cryptopp/blob/master/Test=
Vectors/chacha.txt</a>&gt;. And here are the ones for ChaCha20/Poly1305: &l=
t;<a href=3D"https://github.com/weidai11/cryptopp/blob/master/TestVectors/c=
hacha20poly1305.txt#L4669" rel=3D"nofollow" target=3D"_blank" data-saferedi=
recturl=3D"https://www.google.com/url?hl=3Den&amp;q=3Dhttps://github.com/we=
idai11/cryptopp/blob/master/TestVectors/chacha20poly1305.txt%23L4669&amp;so=
urce=3Dgmail&amp;ust=3D1699543509329000&amp;usg=3DAOvVaw0dRB8k8BxJK5X1_DVzV=
nyc">https://github.com/weidai11/cryptopp/blob/master/TestVectors/chacha20p=
oly1305.txt#L4669</a>&gt;.</div><div><br></div><div>I&#39;m just guessing, =
but the 16-bytes of garbage at the end of the=20
[encrypted] message may be a Poly1305 authentication tag. But it is just
 a guess. The go documentation should tell you what you have.</div><div><br=
></div><div>Jeff<br></div></div></div>
</blockquote></div></blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;Crypto++ Users&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:[email protected]">cryp=
[email protected]</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/d/msgid/cryptopp-users/bbe5ba70-1d8b-4bdd-bfc0-4c176e420da2n%40googlegro=
ups.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.com/d=
/msgid/cryptopp-users/bbe5ba70-1d8b-4bdd-bfc0-4c176e420da2n%40googlegroups.=
com</a>.<br />

------=_Part_40206_244180868.1699457591584--

------=_Part_40205_1235931769.1699457591584--