Skip to content

[go1.20] Override cypto/subtle XORBytes #1284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 11, 2024

Conversation

grantnelson-wf
Copy link
Collaborator

@grantnelson-wf grantnelson-wf commented Apr 3, 2024

The crypto/subtle package added the XORBytes in go1.20. This method XOR's the content of two slices into a third. This is done using unsafe slices to cast []byte slices to []uintptr slices (done to pack registers as full as possible to reduce the number of XOR's being done) or use an architecture specific method for XOR'ing the data.

I added native overrides to XOR 4 bytes at a time via uint32's if possible, otherwise fallback to one byte at a time. This method is 3 to 4 times faster than only doing one byte at a time. However when it has to fallback, it is slightly slower than simply always running one byte at a time because of the alignment and size checks it has to do.

This is part of #1270

@grantnelson-wf grantnelson-wf marked this pull request as ready for review April 3, 2024 22:04
@nevkontakte
Copy link
Member

One possible way to speed this up for UInt8Array is to take its underlying ArrayBuffer and wrap it into UInt32Array(), do xors through it, and then return the result as a UInt8Array again. https://stackoverflow.com/a/68005553/759134 illustrates the idea. However, we do have to be careful about cases when the number of uin8 elements doesn't divide by 4.

LMK if you want to give it a try, otherwise I am okay merging this as-is.

@grantnelson-wf
Copy link
Collaborator Author

One possible way to speed this up for UInt8Array is to take its underlying ArrayBuffer and wrap it into UInt32Array(), do xors through it, and then return the result as a UInt8Array again. https://stackoverflow.com/a/68005553/759134 illustrates the idea. However, we do have to be careful about cases when the number of uin8 elements doesn't divide by 4.

LMK if you want to give it a try, otherwise I am okay merging this as-is.

That's a really great idea. I didn't know that JS could do that kind of cast. That would be better and the existing code in the natives shows how to deal with any dangling bytes (i.e. if len%4 is not zero). I'll see what I can do with JS to make that work, thanks.

@grantnelson-wf grantnelson-wf marked this pull request as draft April 8, 2024 00:46
@grantnelson-wf
Copy link
Collaborator Author

grantnelson-wf commented Apr 8, 2024

Got a version using UInt32Array. I tested it with playground (link to test) and using UInt32Arrays is definitely faster (estimate about 3 to 4 times faster). I'll push up one soon, apparently the offset for UInt32Arrays has to be multiples of 4 so I'll have to do a little more work on it

@grantnelson-wf grantnelson-wf marked this pull request as ready for review April 8, 2024 20:26
@nevkontakte nevkontakte merged commit c331582 into gopherjs:go1.20 Apr 11, 2024
@grantnelson-wf grantnelson-wf deleted the subtleXor branch April 11, 2024 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants