Skip to content

Commit 95f4bef

Browse files
Updating crypto sublte xor overrides
1 parent 0285af6 commit 95f4bef

File tree

1 file changed

+78
-0
lines changed
  • compiler/natives/src/crypto/subtle

1 file changed

+78
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//go:build js
2+
// +build js
3+
4+
package subtle
5+
6+
import "github.com/gopherjs/gopherjs/js"
7+
8+
const wordSize = 4 // bytes for a Uint32Array
9+
10+
func XORBytes(dst, x, y []byte) int {
11+
n := len(x)
12+
if len(y) < n {
13+
n = len(y)
14+
}
15+
if n == 0 {
16+
return 0
17+
}
18+
if n > len(dst) {
19+
panic("subtle.XORBytes: dst too short")
20+
}
21+
22+
// The original uses unsafe and uintptr for specific architecture
23+
// to pack registers full instead of doing one byte at a time.
24+
// We can't do the unsafe conversions from []byte to []uintptr
25+
// but we can convert a Uint8Array into a Uint32Array,
26+
// so we'll simply do it four bytes at a time plus any remainder.
27+
// The following is similar to xorBytes from xor_generic.go
28+
29+
dst = dst[:n]
30+
x = x[:n]
31+
y = y[:n]
32+
if wordCount := n / wordSize; wordCount > 0 &&
33+
aligned(dst) && aligned(x) && aligned(y) {
34+
dstWords := words(dst)
35+
xWords := words(x)
36+
yWords := words(y)
37+
for i := range dstWords {
38+
dstWords[i] = xWords[i] ^ yWords[i]
39+
}
40+
done := n &^ int(wordSize-1)
41+
dst = dst[done:]
42+
x = x[done:]
43+
y = y[done:]
44+
}
45+
for i := range dst {
46+
dst[i] = x[i] ^ y[i]
47+
}
48+
return n
49+
}
50+
51+
// aligned determines whether the slice is word-aligned since
52+
// Uint32Array's require the offset to be multiples of 4.
53+
func aligned(b []byte) bool {
54+
slice := js.InternalObject(b)
55+
offset := slice.Get(`$offset`).Int()
56+
return offset%wordSize == 0
57+
}
58+
59+
// words returns a []uint pointing at the same data as b,
60+
// with any trailing partial word removed.
61+
// The given b must have a word aligned offset.
62+
func words(b []byte) []uint {
63+
slice := js.InternalObject(b)
64+
offset := slice.Get(`$offset`).Int()
65+
length := slice.Get(`$length`).Int()
66+
byteBuffer := slice.Get(`$array`).Get(`buffer`)
67+
wordBuffer := js.Global.Get(`Uint32Array`).New(byteBuffer, offset, length/wordSize)
68+
return wordBuffer.Interface().([]uint)
69+
}
70+
71+
//gopherjs:purge
72+
const supportsUnaligned = false
73+
74+
//gopherjs:purge
75+
func xorBytes(dstb, xb, yb *byte, n int)
76+
77+
//gopherjs:purge
78+
func xorLoop[T byte | uintptr](dst, x, y []T) {}

0 commit comments

Comments
 (0)