-
Notifications
You must be signed in to change notification settings - Fork 12
/
rc4.go
66 lines (58 loc) · 1.75 KB
/
rc4.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//go:build !cmd_go_bootstrap
package openssl
// #include "goopenssl.h"
import "C"
import "runtime"
// SupportsRC4 returns true if NewRC4Cipher is supported.
func SupportsRC4() bool {
// True for stock OpenSSL 1 w/o FIPS.
// False for stock OpenSSL 3 unless the legacy provider is available.
return (versionAtOrAbove(3, 0, 0) || !FIPS()) && loadCipher(cipherRC4, cipherModeNone) != nil
}
// A RC4Cipher is an instance of RC4 using a particular key.
type RC4Cipher struct {
ctx C.GO_EVP_CIPHER_CTX_PTR
}
// NewRC4Cipher creates and returns a new Cipher.
func NewRC4Cipher(key []byte) (*RC4Cipher, error) {
ctx, err := newCipherCtx(cipherRC4, cipherModeNone, cipherOpEncrypt, key, nil)
if err != nil {
return nil, err
}
c := &RC4Cipher{ctx}
runtime.SetFinalizer(c, (*RC4Cipher).finalize)
return c, nil
}
func (c *RC4Cipher) finalize() {
if c.ctx != nil {
C.go_openssl_EVP_CIPHER_CTX_free(c.ctx)
}
}
// Reset zeros the key data and makes the Cipher unusable.
func (c *RC4Cipher) Reset() {
if c.ctx != nil {
C.go_openssl_EVP_CIPHER_CTX_free(c.ctx)
c.ctx = nil
}
}
// XORKeyStream sets dst to the result of XORing src with the key stream.
// Dst and src must overlap entirely or not at all.
func (c *RC4Cipher) XORKeyStream(dst, src []byte) {
if c.ctx == nil || len(src) == 0 {
return
}
if inexactOverlap(dst[:len(src)], src) {
panic("crypto/rc4: invalid buffer overlap")
}
// panic if len(dst) < len(src) with a runtime out of bound error,
// which is what crypto/rc4 does.
_ = dst[len(src)-1]
var outLen C.int
if C.go_openssl_EVP_EncryptUpdate(c.ctx, base(dst), &outLen, base(src), C.int(len(src))) != 1 {
panic("crypto/cipher: EncryptUpdate failed")
}
if int(outLen) != len(src) {
panic("crypto/rc4: src not fully XORed")
}
runtime.KeepAlive(c)
}