Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
ad67a866
Commit
ad67a866
authored
Nov 02, 2009
by
Adam Langley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split constant time functions into crypto/subtle.
R=rsc CC=go-dev
http://go/go-review/1018020
parent
d0024898
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
249 additions
and
216 deletions
+249
-216
Make.deps
src/pkg/Make.deps
+1
-0
Makefile
src/pkg/Makefile
+1
-0
pkcs1v15.go
src/pkg/crypto/rsa/pkcs1v15.go
+10
-9
rsa.go
src/pkg/crypto/rsa/rsa.go
+14
-65
rsa_test.go
src/pkg/crypto/rsa/rsa_test.go
+47
-142
Makefile
src/pkg/crypto/subtle/Makefile
+11
-0
constant_time.go
src/pkg/crypto/subtle/constant_time.go
+59
-0
constant_time_test.go
src/pkg/crypto/subtle/constant_time_test.go
+106
-0
No files found.
src/pkg/Make.deps
View file @
ad67a866
...
...
@@ -17,6 +17,7 @@ crypto/hmac.install: crypto/md5.install crypto/sha1.install hash.install os.inst
crypto/md5.install: hash.install os.install
crypto/rc4.install: os.install strconv.install
crypto/sha1.install: hash.install os.install
crypto/subtle.install:
debug/dwarf.install: encoding/binary.install os.install strconv.install
debug/macho.install: bytes.install debug/dwarf.install encoding/binary.install fmt.install io.install os.install strconv.install
debug/elf.install: debug/dwarf.install encoding/binary.install fmt.install io.install os.install strconv.install
...
...
src/pkg/Makefile
View file @
ad67a866
...
...
@@ -31,6 +31,7 @@ DIRS=\
crypto/md5
\
crypto/rc4
\
crypto/sha1
\
crypto/subtle
\
debug/dwarf
\
debug/macho
\
debug/elf
\
...
...
src/pkg/crypto/rsa/pkcs1v15.go
View file @
ad67a866
...
...
@@ -6,6 +6,7 @@ package rsa
import
(
"bytes"
;
"crypto/subtle"
;
big
"gmp"
;
"io"
;
"os"
;
...
...
@@ -27,7 +28,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
// EM = 0x02 || PS || 0x00 || M
em
:=
make
([]
byte
,
k
-
1
);
em
[
0
]
=
2
;
ps
,
mm
:=
em
[
1
:
len
(
em
)
-
len
(
msg
)
-
1
],
em
[
len
(
em
)
-
len
(
msg
)
:
len
(
em
)];
ps
,
mm
:=
em
[
1
:
len
(
em
)
-
len
(
msg
)
-
1
],
em
[
len
(
em
)
-
len
(
msg
)
:
len
(
em
)];
err
=
nonZeroRandomBytes
(
ps
,
rand
);
if
err
!=
nil
{
return
;
...
...
@@ -77,8 +78,8 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by
return
;
}
valid
&=
c
onstantTimeEq
(
int32
(
len
(
msg
)),
int32
(
len
(
key
)));
c
onstantTimeCopy
(
valid
,
key
,
msg
);
valid
&=
subtle
.
C
onstantTimeEq
(
int32
(
len
(
msg
)),
int32
(
len
(
key
)));
subtle
.
C
onstantTimeCopy
(
valid
,
key
,
msg
);
return
;
}
...
...
@@ -96,8 +97,8 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
}
em
:=
leftPad
(
m
.
Bytes
(),
k
);
firstByteIsZero
:=
c
onstantTimeByteEq
(
em
[
0
],
0
);
secondByteIsTwo
:=
c
onstantTimeByteEq
(
em
[
1
],
2
);
firstByteIsZero
:=
subtle
.
C
onstantTimeByteEq
(
em
[
0
],
0
);
secondByteIsTwo
:=
subtle
.
C
onstantTimeByteEq
(
em
[
1
],
2
);
// The remainder of the plaintext must be a string of non-zero random
// octets, followed by a 0, followed by the message.
...
...
@@ -107,9 +108,9 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
lookingForIndex
=
1
;
for
i
:=
2
;
i
<
len
(
em
);
i
++
{
equals0
:=
c
onstantTimeByteEq
(
em
[
i
],
0
);
index
=
c
onstantTimeSelect
(
lookingForIndex
&
equals0
,
i
,
index
);
lookingForIndex
=
c
onstantTimeSelect
(
equals0
,
0
,
lookingForIndex
);
equals0
:=
subtle
.
C
onstantTimeByteEq
(
em
[
i
],
0
);
index
=
subtle
.
C
onstantTimeSelect
(
lookingForIndex
&
equals0
,
i
,
index
);
lookingForIndex
=
subtle
.
C
onstantTimeSelect
(
equals0
,
0
,
lookingForIndex
);
}
valid
=
firstByteIsZero
&
secondByteIsTwo
&
(
^
lookingForIndex
&
1
);
...
...
@@ -126,7 +127,7 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
for
i
:=
0
;
i
<
len
(
s
);
i
++
{
for
s
[
i
]
==
0
{
_
,
err
=
rand
.
Read
(
s
[
i
:
i
+
1
]);
_
,
err
=
rand
.
Read
(
s
[
i
:
i
+
1
]);
if
err
!=
nil
{
return
;
}
...
...
src/pkg/crypto/rsa/rsa.go
View file @
ad67a866
...
...
@@ -8,11 +8,12 @@ package rsa
// TODO(agl): Add support for PSS padding.
import
(
"bytes"
;
big
"gmp"
;
"hash"
;
"io"
;
"os"
;
"bytes"
;
"crypto/subtle"
;
big
"gmp"
;
"hash"
;
"io"
;
"os"
;
)
var
bigOne
=
big
.
NewInt
(
1
)
...
...
@@ -92,7 +93,7 @@ type PublicKey struct {
// A PrivateKey represents an RSA key
type
PrivateKey
struct
{
PublicKey
;
// public part.
PublicKey
;
// public part.
D
*
big
.
Int
;
// private exponent
P
,
Q
*
big
.
Int
;
// prime factors of N
}
...
...
@@ -300,58 +301,6 @@ func modInverse(a, n *big.Int) (ia *big.Int) {
return
x
;
}
// constantTimeCompare returns 1 iff the two equal length slices, x
// and y, have equal contents. The time taken is a function of the length of
// the slices and is independent of the contents.
func
constantTimeCompare
(
x
,
y
[]
byte
)
int
{
var
v
byte
;
for
i
:=
0
;
i
<
len
(
x
);
i
++
{
v
|=
x
[
i
]
^
y
[
i
];
}
return
constantTimeByteEq
(
v
,
0
);
}
// constantTimeSelect returns a if v is 1 and b if v is 0.
// Its behaviour is undefined if v takes any other value.
func
constantTimeSelect
(
v
,
a
,
b
int
)
int
{
return
^
(
v
-
1
)
&
a
|
(
v
-
1
)
&
b
;
}
// constantTimeByteEq returns 1 if a == b and 0 otherwise.
func
constantTimeByteEq
(
a
,
b
uint8
)
int
{
x
:=
^
(
a
^
b
);
x
&=
x
>>
4
;
x
&=
x
>>
2
;
x
&=
x
>>
1
;
return
int
(
x
);
}
// constantTimeEq returns 1 if a == b and 0 otherwise.
func
constantTimeEq
(
a
,
b
int32
)
int
{
x
:=
^
(
a
^
b
);
x
&=
x
>>
16
;
x
&=
x
>>
8
;
x
&=
x
>>
4
;
x
&=
x
>>
2
;
x
&=
x
>>
1
;
return
int
(
x
&
1
);
}
// constantTimeCopy copies the contents of y into x iff v == 1. If v == 0, x is left unchanged.
// Its behaviour is undefined if v takes any other value.
func
constantTimeCopy
(
v
int
,
x
,
y
[]
byte
)
{
xmask
:=
byte
(
v
-
1
);
ymask
:=
byte
(
^
(
v
-
1
));
for
i
:=
0
;
i
<
len
(
x
);
i
++
{
x
[
i
]
=
x
[
i
]
&
xmask
|
y
[
i
]
&
ymask
;
}
return
;
}
// decrypt performs an RSA decryption, resulting in a plaintext integer. If a
// random source is given, RSA blinding is used.
func
decrypt
(
rand
io
.
Reader
,
priv
*
PrivateKey
,
c
*
big
.
Int
)
(
m
*
big
.
Int
,
err
os
.
Error
)
{
...
...
@@ -419,7 +368,7 @@ func DecryptOAEP(hash hash.Hash, rand io.Reader, priv *PrivateKey, ciphertext []
// anything about this.)
em
:=
leftPad
(
m
.
Bytes
(),
k
);
firstByteIsZero
:=
c
onstantTimeByteEq
(
em
[
0
],
0
);
firstByteIsZero
:=
subtle
.
C
onstantTimeByteEq
(
em
[
0
],
0
);
seed
:=
em
[
1
:
hash
.
Size
()
+
1
];
db
:=
em
[
hash
.
Size
()
+
1
:
len
(
em
)];
...
...
@@ -433,7 +382,7 @@ func DecryptOAEP(hash hash.Hash, rand io.Reader, priv *PrivateKey, ciphertext []
// attacks like: J. Manger. A Chosen Ciphertext Attack on RSA Optimal
// Asymmetric Encryption Padding (OAEP) as Standardized in PKCS #1
// v2.0. In J. Kilian, editor, Advances in Cryptology.
lHash2Good
:=
c
onstantTimeCompare
(
lHash
,
lHash2
);
lHash2Good
:=
subtle
.
C
onstantTimeCompare
(
lHash
,
lHash2
);
// The remainder of the plaintext must be zero or more 0x00, followed
// by 0x01, followed by the message.
...
...
@@ -445,11 +394,11 @@ func DecryptOAEP(hash hash.Hash, rand io.Reader, priv *PrivateKey, ciphertext []
rest
:=
db
[
hash
.
Size
()
:
len
(
db
)];
for
i
:=
0
;
i
<
len
(
rest
);
i
++
{
equals0
:=
c
onstantTimeByteEq
(
rest
[
i
],
0
);
equals1
:=
c
onstantTimeByteEq
(
rest
[
i
],
1
);
index
=
c
onstantTimeSelect
(
lookingForIndex
&
equals1
,
i
,
index
);
lookingForIndex
=
c
onstantTimeSelect
(
equals1
,
0
,
lookingForIndex
);
invalid
=
c
onstantTimeSelect
(
lookingForIndex
&
^
equals0
,
1
,
invalid
);
equals0
:=
subtle
.
C
onstantTimeByteEq
(
rest
[
i
],
0
);
equals1
:=
subtle
.
C
onstantTimeByteEq
(
rest
[
i
],
1
);
index
=
subtle
.
C
onstantTimeSelect
(
lookingForIndex
&
equals1
,
i
,
index
);
lookingForIndex
=
subtle
.
C
onstantTimeSelect
(
equals1
,
0
,
lookingForIndex
);
invalid
=
subtle
.
C
onstantTimeSelect
(
lookingForIndex
&
^
equals0
,
1
,
invalid
);
}
if
firstByteIsZero
&
lHash2Good
&
^
invalid
&
^
lookingForIndex
!=
1
{
...
...
src/pkg/crypto/rsa/rsa_test.go
View file @
ad67a866
...
...
@@ -5,12 +5,11 @@
package
rsa
import
(
"bytes"
;
"crypto/sha1"
;
big
"gmp"
;
"os"
;
"testing"
;
"testing/quick"
;
"bytes"
;
"crypto/sha1"
;
big
"gmp"
;
"os"
;
"testing"
;
)
func
TestKeyGeneration
(
t
*
testing
.
T
)
{
...
...
@@ -109,101 +108,6 @@ func TestDecryptOAEP(t *testing.T) {
}
}
type
TestConstantTimeCompareStruct
struct
{
a
,
b
[]
byte
;
out
int
;
}
var
testConstandTimeCompareData
=
[]
TestConstantTimeCompareStruct
{
TestConstantTimeCompareStruct
{[]
byte
{},
[]
byte
{},
1
},
TestConstantTimeCompareStruct
{[]
byte
{
0x11
},
[]
byte
{
0x11
},
1
},
TestConstantTimeCompareStruct
{[]
byte
{
0x12
},
[]
byte
{
0x11
},
0
},
}
func
TestConstantTimeCompare
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
testConstandTimeCompareData
{
if
r
:=
constantTimeCompare
(
test
.
a
,
test
.
b
);
r
!=
test
.
out
{
t
.
Errorf
(
"#%d bad result (got %x, want %x)"
,
i
,
r
,
test
.
out
);
}
}
}
type
TestConstantTimeByteEqStruct
struct
{
a
,
b
uint8
;
out
int
;
}
var
testConstandTimeByteEqData
=
[]
TestConstantTimeByteEqStruct
{
TestConstantTimeByteEqStruct
{
0
,
0
,
1
},
TestConstantTimeByteEqStruct
{
0
,
1
,
0
},
TestConstantTimeByteEqStruct
{
1
,
0
,
0
},
TestConstantTimeByteEqStruct
{
0xff
,
0xff
,
1
},
TestConstantTimeByteEqStruct
{
0xff
,
0xfe
,
0
},
}
func
ByteEq
(
a
,
b
uint8
)
int
{
if
a
==
b
{
return
1
;
}
return
0
;
}
func
TestConstantTimeByteEq
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
testConstandTimeByteEqData
{
if
r
:=
constantTimeByteEq
(
test
.
a
,
test
.
b
);
r
!=
test
.
out
{
t
.
Errorf
(
"#%d bad result (got %x, want %x)"
,
i
,
r
,
test
.
out
);
}
}
err
:=
quick
.
CheckEqual
(
constantTimeByteEq
,
ByteEq
,
nil
);
if
err
!=
nil
{
t
.
Error
(
err
);
}
}
func
Eq
(
a
,
b
int32
)
int
{
if
a
==
b
{
return
1
;
}
return
0
;
}
func
TestConstantTimeEq
(
t
*
testing
.
T
)
{
err
:=
quick
.
CheckEqual
(
constantTimeEq
,
Eq
,
nil
);
if
err
!=
nil
{
t
.
Error
(
err
);
}
}
func
Copy
(
v
int
,
x
,
y
[]
byte
)
[]
byte
{
if
len
(
x
)
>
len
(
y
)
{
x
=
x
[
0
:
len
(
y
)];
}
else
{
y
=
y
[
0
:
len
(
x
)];
}
if
v
==
1
{
bytes
.
Copy
(
x
,
y
);
}
return
x
;
}
func
constantTimeCopyWrapper
(
v
int
,
x
,
y
[]
byte
)
[]
byte
{
if
len
(
x
)
>
len
(
y
)
{
x
=
x
[
0
:
len
(
y
)];
}
else
{
y
=
y
[
0
:
len
(
x
)];
}
v
&=
1
;
constantTimeCopy
(
v
,
x
,
y
);
return
x
;
}
func
TestConstantTimeCopy
(
t
*
testing
.
T
)
{
err
:=
quick
.
CheckEqual
(
constantTimeCopyWrapper
,
Copy
,
nil
);
if
err
!=
nil
{
t
.
Error
(
err
);
}
}
// testEncryptOAEPData contains a subset of the vectors from RSA's "Test vectors for RSA-OAEP".
var
testEncryptOAEPData
=
[]
testEncryptOAEPStruct
{
// Key 1
...
...
@@ -305,47 +209,48 @@ var testEncryptOAEPData = []testEncryptOAEPStruct{
65537
,
"056b04216fe5f354ac77250a4b6b0c8525a85c59b0bd80c56450a22d5f438e596a333aa875e291dd43f48cb88b9d5fc0d499f9fcd1c397f9afc070cd9e398c8d19e61db7c7410a6b2675dfbf5d345b804d201add502d5ce2dfcb091ce9997bbebe57306f383e4d588103f036f7e85d1934d152a323e4a8db451d6f4a5b1b0f102cc150e02feee2b88dea4ad4c1baccb24d84072d14e1d24a6771f7408ee30564fb86d4393a34bcf0b788501d193303f13a2284b001f0f649eaf79328d4ac5c430ab4414920a9460ed1b7bc40ec653e876d09abc509ae45b525190116a0c26101848298509c1c3bf3a483e7274054e15e97075036e989f60932807b5257751e79"
,
[]
testEncryptOAEPMessage
{
// Example 10.1
testEncryptOAEPMessage
{
[]
byte
{
0x8b
,
0xba
,
0x6b
,
0xf8
,
0x2a
,
0x6c
,
0x0f
,
0x86
,
0xd5
,
0xf1
,
0x75
,
0x6e
,
0x97
,
0x95
,
0x68
,
0x70
,
0xb0
,
0x89
,
0x53
,
0xb0
,
0x6b
,
0x4e
,
0xb2
,
0x05
,
0xbc
,
0x16
,
0x94
,
0xee
,
},
[]
byte
{
0x47
,
0xe1
,
0xab
,
0x71
,
0x19
,
0xfe
,
0xe5
,
0x6c
,
0x95
,
0xee
,
0x5e
,
0xaa
,
0xd8
,
0x6f
,
0x40
,
0xd0
,
0xaa
,
0x63
,
0xbd
,
0x33
,
},
[]
byte
{
0x53
,
0xea
,
0x5d
,
0xc0
,
0x8c
,
0xd2
,
0x60
,
0xfb
,
0x3b
,
0x85
,
0x85
,
0x67
,
0x28
,
0x7f
,
0xa9
,
0x15
,
0x52
,
0xc3
,
0x0b
,
0x2f
,
0xeb
,
0xfb
,
0xa2
,
0x13
,
0xf0
,
0xae
,
0x87
,
0x70
,
0x2d
,
0x06
,
0x8d
,
0x19
,
0xba
,
0xb0
,
0x7f
,
0xe5
,
0x74
,
0x52
,
0x3d
,
0xfb
,
0x42
,
0x13
,
0x9d
,
0x68
,
0xc3
,
0xc5
,
0xaf
,
0xee
,
0xe0
,
0xbf
,
0xe4
,
0xcb
,
0x79
,
0x69
,
0xcb
,
0xf3
,
0x82
,
0xb8
,
0x04
,
0xd6
,
0xe6
,
0x13
,
0x96
,
0x14
,
0x4e
,
0x2d
,
0x0e
,
0x60
,
0x74
,
0x1f
,
0x89
,
0x93
,
0xc3
,
0x01
,
0x4b
,
0x58
,
0xb9
,
0xb1
,
0x95
,
0x7a
,
0x8b
,
0xab
,
0xcd
,
0x23
,
0xaf
,
0x85
,
0x4f
,
0x4c
,
0x35
,
0x6f
,
0xb1
,
0x66
,
0x2a
,
0xa7
,
0x2b
,
0xfc
,
0xc7
,
0xe5
,
0x86
,
0x55
,
0x9d
,
0xc4
,
0x28
,
0x0d
,
0x16
,
0x0c
,
0x12
,
0x67
,
0x85
,
0xa7
,
0x23
,
0xeb
,
0xee
,
0xbe
,
0xff
,
0x71
,
0xf1
,
0x15
,
0x94
,
0x44
,
0x0a
,
0xae
,
0xf8
,
0x7d
,
0x10
,
0x79
,
0x3a
,
0x87
,
0x74
,
0xa2
,
0x39
,
0xd4
,
0xa0
,
0x4c
,
0x87
,
0xfe
,
0x14
,
0x67
,
0xb9
,
0xda
,
0xf8
,
0x52
,
0x08
,
0xec
,
0x6c
,
0x72
,
0x55
,
0x79
,
0x4a
,
0x96
,
0xcc
,
0x29
,
0x14
,
0x2f
,
0x9a
,
0x8b
,
0xd4
,
0x18
,
0xe3
,
0xc1
,
0xfd
,
0x67
,
0x34
,
0x4b
,
0x0c
,
0xd0
,
0x82
,
0x9d
,
0xf3
,
0xb2
,
0xbe
,
0xc6
,
0x02
,
0x53
,
0x19
,
0x62
,
0x93
,
0xc6
,
0xb3
,
0x4d
,
0x3f
,
0x75
,
0xd3
,
0x2f
,
0x21
,
0x3d
,
0xd4
,
0x5c
,
0x62
,
0x73
,
0xd5
,
0x05
,
0xad
,
0xf4
,
0xcc
,
0xed
,
0x10
,
0x57
,
0xcb
,
0x75
,
0x8f
,
0xc2
,
0x6a
,
0xee
,
0xfa
,
0x44
,
0x12
,
0x55
,
0xed
,
0x4e
,
0x64
,
0xc1
,
0x99
,
0xee
,
0x07
,
0x5e
,
0x7f
,
0x16
,
0x64
,
0x61
,
0x82
,
0xfd
,
0xb4
,
0x64
,
0x73
,
0x9b
,
0x68
,
0xab
,
0x5d
,
0xaf
,
0xf0
,
0xe6
,
0x3e
,
0x95
,
0x52
,
0x01
,
0x68
,
0x24
,
0xf0
,
0x54
,
0xbf
,
0x4d
,
0x3c
,
0x8c
,
0x90
,
0xa9
,
0x7b
,
0xb6
,
0xb6
,
0x55
,
0x32
,
0x84
,
0xeb
,
0x42
,
0x9f
,
0xcc
,
// Example 10.1
testEncryptOAEPMessage
{
[]
byte
{
0x8b
,
0xba
,
0x6b
,
0xf8
,
0x2a
,
0x6c
,
0x0f
,
0x86
,
0xd5
,
0xf1
,
0x75
,
0x6e
,
0x97
,
0x95
,
0x68
,
0x70
,
0xb0
,
0x89
,
0x53
,
0xb0
,
0x6b
,
0x4e
,
0xb2
,
0x05
,
0xbc
,
0x16
,
0x94
,
0xee
,
},
[]
byte
{
0x47
,
0xe1
,
0xab
,
0x71
,
0x19
,
0xfe
,
0xe5
,
0x6c
,
0x95
,
0xee
,
0x5e
,
0xaa
,
0xd8
,
0x6f
,
0x40
,
0xd0
,
0xaa
,
0x63
,
0xbd
,
0x33
,
},
[]
byte
{
0x53
,
0xea
,
0x5d
,
0xc0
,
0x8c
,
0xd2
,
0x60
,
0xfb
,
0x3b
,
0x85
,
0x85
,
0x67
,
0x28
,
0x7f
,
0xa9
,
0x15
,
0x52
,
0xc3
,
0x0b
,
0x2f
,
0xeb
,
0xfb
,
0xa2
,
0x13
,
0xf0
,
0xae
,
0x87
,
0x70
,
0x2d
,
0x06
,
0x8d
,
0x19
,
0xba
,
0xb0
,
0x7f
,
0xe5
,
0x74
,
0x52
,
0x3d
,
0xfb
,
0x42
,
0x13
,
0x9d
,
0x68
,
0xc3
,
0xc5
,
0xaf
,
0xee
,
0xe0
,
0xbf
,
0xe4
,
0xcb
,
0x79
,
0x69
,
0xcb
,
0xf3
,
0x82
,
0xb8
,
0x04
,
0xd6
,
0xe6
,
0x13
,
0x96
,
0x14
,
0x4e
,
0x2d
,
0x0e
,
0x60
,
0x74
,
0x1f
,
0x89
,
0x93
,
0xc3
,
0x01
,
0x4b
,
0x58
,
0xb9
,
0xb1
,
0x95
,
0x7a
,
0x8b
,
0xab
,
0xcd
,
0x23
,
0xaf
,
0x85
,
0x4f
,
0x4c
,
0x35
,
0x6f
,
0xb1
,
0x66
,
0x2a
,
0xa7
,
0x2b
,
0xfc
,
0xc7
,
0xe5
,
0x86
,
0x55
,
0x9d
,
0xc4
,
0x28
,
0x0d
,
0x16
,
0x0c
,
0x12
,
0x67
,
0x85
,
0xa7
,
0x23
,
0xeb
,
0xee
,
0xbe
,
0xff
,
0x71
,
0xf1
,
0x15
,
0x94
,
0x44
,
0x0a
,
0xae
,
0xf8
,
0x7d
,
0x10
,
0x79
,
0x3a
,
0x87
,
0x74
,
0xa2
,
0x39
,
0xd4
,
0xa0
,
0x4c
,
0x87
,
0xfe
,
0x14
,
0x67
,
0xb9
,
0xda
,
0xf8
,
0x52
,
0x08
,
0xec
,
0x6c
,
0x72
,
0x55
,
0x79
,
0x4a
,
0x96
,
0xcc
,
0x29
,
0x14
,
0x2f
,
0x9a
,
0x8b
,
0xd4
,
0x18
,
0xe3
,
0xc1
,
0xfd
,
0x67
,
0x34
,
0x4b
,
0x0c
,
0xd0
,
0x82
,
0x9d
,
0xf3
,
0xb2
,
0xbe
,
0xc6
,
0x02
,
0x53
,
0x19
,
0x62
,
0x93
,
0xc6
,
0xb3
,
0x4d
,
0x3f
,
0x75
,
0xd3
,
0x2f
,
0x21
,
0x3d
,
0xd4
,
0x5c
,
0x62
,
0x73
,
0xd5
,
0x05
,
0xad
,
0xf4
,
0xcc
,
0xed
,
0x10
,
0x57
,
0xcb
,
0x75
,
0x8f
,
0xc2
,
0x6a
,
0xee
,
0xfa
,
0x44
,
0x12
,
0x55
,
0xed
,
0x4e
,
0x64
,
0xc1
,
0x99
,
0xee
,
0x07
,
0x5e
,
0x7f
,
0x16
,
0x64
,
0x61
,
0x82
,
0xfd
,
0xb4
,
0x64
,
0x73
,
0x9b
,
0x68
,
0xab
,
0x5d
,
0xaf
,
0xf0
,
0xe6
,
0x3e
,
0x95
,
0x52
,
0x01
,
0x68
,
0x24
,
0xf0
,
0x54
,
0xbf
,
0x4d
,
0x3c
,
0x8c
,
0x90
,
0xa9
,
0x7b
,
0xb6
,
0xb6
,
0x55
,
0x32
,
0x84
,
0xeb
,
0x42
,
0x9f
,
0xcc
,
},
},
}
}
,
},
},
}
src/pkg/crypto/subtle/Makefile
0 → 100644
View file @
ad67a866
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include
$(GOROOT)/src/Make.$(GOARCH)
TARG
=
crypto/subtle
GOFILES
=
\
constant_time.go
\
include
$(GOROOT)/src/Make.pkg
src/pkg/crypto/subtle/constant_time.go
0 → 100644
View file @
ad67a866
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This package implements functions that are often useful in cryptographic
// code but require careful thought to use correctly.
package
subtle
// ConstantTimeCompare returns 1 iff the two equal length slices, x
// and y, have equal contents. The time taken is a function of the length of
// the slices and is independent of the contents.
func
ConstantTimeCompare
(
x
,
y
[]
byte
)
int
{
var
v
byte
;
for
i
:=
0
;
i
<
len
(
x
);
i
++
{
v
|=
x
[
i
]
^
y
[
i
];
}
return
ConstantTimeByteEq
(
v
,
0
);
}
// ConstantTimeSelect returns x if v is 1 and y if v is 0.
// Its behavior is undefined if v takes any other value.
func
ConstantTimeSelect
(
v
,
x
,
y
int
)
int
{
return
^
(
v
-
1
)
&
x
|
(
v
-
1
)
&
y
;
}
// ConstantTimeByteEq returns 1 if x == x and 0 otherwise.
func
ConstantTimeByteEq
(
x
,
y
uint8
)
int
{
z
:=
^
(
x
^
y
);
z
&=
z
>>
4
;
z
&=
z
>>
2
;
z
&=
z
>>
1
;
return
int
(
z
);
}
// ConstantTimeEq returns 1 if x == y and 0 otherwise.
func
ConstantTimeEq
(
x
,
y
int32
)
int
{
z
:=
^
(
x
^
y
);
z
&=
z
>>
16
;
z
&=
z
>>
8
;
z
&=
z
>>
4
;
z
&=
z
>>
2
;
z
&=
z
>>
1
;
return
int
(
z
&
1
);
}
// ConstantTimeCopy copies the contents of y into x iff v == 1. If v == 0, x is left unchanged.
// Its behavior is undefined if v takes any other value.
func
ConstantTimeCopy
(
v
int
,
x
,
y
[]
byte
)
{
xmask
:=
byte
(
v
-
1
);
ymask
:=
byte
(
^
(
v
-
1
));
for
i
:=
0
;
i
<
len
(
x
);
i
++
{
x
[
i
]
=
x
[
i
]
&
xmask
|
y
[
i
]
&
ymask
;
}
return
;
}
src/pkg/crypto/subtle/constant_time_test.go
0 → 100644
View file @
ad67a866
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
subtle
import
(
"bytes"
;
"testing"
;
"testing/quick"
;
)
type
TestConstantTimeCompareStruct
struct
{
a
,
b
[]
byte
;
out
int
;
}
var
testConstandTimeCompareData
=
[]
TestConstantTimeCompareStruct
{
TestConstantTimeCompareStruct
{[]
byte
{},
[]
byte
{},
1
},
TestConstantTimeCompareStruct
{[]
byte
{
0x11
},
[]
byte
{
0x11
},
1
},
TestConstantTimeCompareStruct
{[]
byte
{
0x12
},
[]
byte
{
0x11
},
0
},
}
func
TestConstantTimeCompare
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
testConstandTimeCompareData
{
if
r
:=
ConstantTimeCompare
(
test
.
a
,
test
.
b
);
r
!=
test
.
out
{
t
.
Errorf
(
"#%d bad result (got %x, want %x)"
,
i
,
r
,
test
.
out
);
}
}
}
type
TestConstantTimeByteEqStruct
struct
{
a
,
b
uint8
;
out
int
;
}
var
testConstandTimeByteEqData
=
[]
TestConstantTimeByteEqStruct
{
TestConstantTimeByteEqStruct
{
0
,
0
,
1
},
TestConstantTimeByteEqStruct
{
0
,
1
,
0
},
TestConstantTimeByteEqStruct
{
1
,
0
,
0
},
TestConstantTimeByteEqStruct
{
0xff
,
0xff
,
1
},
TestConstantTimeByteEqStruct
{
0xff
,
0xfe
,
0
},
}
func
byteEq
(
a
,
b
uint8
)
int
{
if
a
==
b
{
return
1
;
}
return
0
;
}
func
TestConstantTimeByteEq
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
testConstandTimeByteEqData
{
if
r
:=
ConstantTimeByteEq
(
test
.
a
,
test
.
b
);
r
!=
test
.
out
{
t
.
Errorf
(
"#%d bad result (got %x, want %x)"
,
i
,
r
,
test
.
out
);
}
}
err
:=
quick
.
CheckEqual
(
ConstantTimeByteEq
,
byteEq
,
nil
);
if
err
!=
nil
{
t
.
Error
(
err
);
}
}
func
eq
(
a
,
b
int32
)
int
{
if
a
==
b
{
return
1
;
}
return
0
;
}
func
TestConstantTimeEq
(
t
*
testing
.
T
)
{
err
:=
quick
.
CheckEqual
(
ConstantTimeEq
,
eq
,
nil
);
if
err
!=
nil
{
t
.
Error
(
err
);
}
}
func
copy
(
v
int
,
x
,
y
[]
byte
)
[]
byte
{
if
len
(
x
)
>
len
(
y
)
{
x
=
x
[
0
:
len
(
y
)];
}
else
{
y
=
y
[
0
:
len
(
x
)];
}
if
v
==
1
{
bytes
.
Copy
(
x
,
y
);
}
return
x
;
}
func
constantTimeCopyWrapper
(
v
int
,
x
,
y
[]
byte
)
[]
byte
{
if
len
(
x
)
>
len
(
y
)
{
x
=
x
[
0
:
len
(
y
)];
}
else
{
y
=
y
[
0
:
len
(
x
)];
}
v
&=
1
;
ConstantTimeCopy
(
v
,
x
,
y
);
return
x
;
}
func
TestConstantTimeCopy
(
t
*
testing
.
T
)
{
err
:=
quick
.
CheckEqual
(
constantTimeCopyWrapper
,
copy
,
nil
);
if
err
!=
nil
{
t
.
Error
(
err
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment