Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
G
Go
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Martin Stiemerling
Go
Commits
a8ba4082
Commit
a8ba4082
authored
15 years ago
by
Adam Langley
Browse files
Options
Downloads
Patches
Plain Diff
crypto/rsa: add PKCS#1 v1.5 signature support.
R=rsc CC=golang-dev
https://golang.org/cl/156051
parent
80b7f6a8
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/pkg/crypto/rsa/pkcs1v15.go
+128
-0
128 additions, 0 deletions
src/pkg/crypto/rsa/pkcs1v15.go
src/pkg/crypto/rsa/pkcs1v15_test.go
+45
-0
45 additions, 0 deletions
src/pkg/crypto/rsa/pkcs1v15_test.go
src/pkg/crypto/rsa/rsa.go
+6
-0
6 additions, 0 deletions
src/pkg/crypto/rsa/rsa.go
with
179 additions
and
0 deletions
src/pkg/crypto/rsa/pkcs1v15.go
+
128
−
0
View file @
a8ba4082
...
...
@@ -136,3 +136,131 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
return
;
}
// Due to the design of PKCS#1 v1.5, we need to know the exact hash function in
// use. A generic hash.Hash will not do.
type
PKCS1v15Hash
int
const
(
HashMD5
PKCS1v15Hash
=
iota
;
HashSHA1
;
HashSHA256
;
HashSHA384
;
HashSHA512
;
)
// These are ASN1 DER structures:
// DigestInfo ::= SEQUENCE {
// digestAlgorithm AlgorithmIdentifier,
// digest OCTET STRING
// }
// For performance, we don't use the generic ASN1 encoding. Rather, we
// precompute a prefix of the digest value that makes a valid ASN1 DER string
// with the correct contents.
var
hashPrefixes
=
[][]
byte
{
// HashMD5
[]
byte
{
0x30
,
0x20
,
0x30
,
0x0c
,
0x06
,
0x08
,
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x02
,
0x05
,
0x05
,
0x00
,
0x04
,
0x10
},
// HashSHA1
[]
byte
{
0x30
,
0x21
,
0x30
,
0x09
,
0x06
,
0x05
,
0x2b
,
0x0e
,
0x03
,
0x02
,
0x1a
,
0x05
,
0x00
,
0x04
,
0x14
},
// HashSHA256
[]
byte
{
0x30
,
0x31
,
0x30
,
0x0d
,
0x06
,
0x09
,
0x60
,
0x86
,
0x48
,
0x01
,
0x65
,
0x03
,
0x04
,
0x02
,
0x01
,
0x05
,
0x00
,
0x04
,
0x20
},
// HashSHA384
[]
byte
{
0x30
,
0x41
,
0x30
,
0x0d
,
0x06
,
0x09
,
0x60
,
0x86
,
0x48
,
0x01
,
0x65
,
0x03
,
0x04
,
0x02
,
0x02
,
0x05
,
0x00
,
0x04
,
0x30
},
// HashSHA512
[]
byte
{
0x30
,
0x51
,
0x30
,
0x0d
,
0x06
,
0x09
,
0x60
,
0x86
,
0x48
,
0x01
,
0x65
,
0x03
,
0x04
,
0x02
,
0x03
,
0x05
,
0x00
,
0x04
,
0x40
},
}
// SignPKCS1v15 calcuates the signature of hashed using RSASSA-PSS-SIGN from RSA PKCS#1 v1.5.
// Note that hashed must be the result of hashing the input message using the
// given hash function.
func
SignPKCS1v15
(
rand
io
.
Reader
,
priv
*
PrivateKey
,
hash
PKCS1v15Hash
,
hashed
[]
byte
)
(
s
[]
byte
,
err
os
.
Error
)
{
hashLen
,
prefix
,
err
:=
pkcs1v15HashInfo
(
hash
,
len
(
hashed
));
if
err
!=
nil
{
return
}
tLen
:=
len
(
prefix
)
+
hashLen
;
k
:=
(
priv
.
N
.
Len
()
+
7
)
/
8
;
if
k
<
tLen
+
11
{
return
nil
,
MessageTooLongError
{}
}
// EM = 0x00 || 0x01 || PS || 0x00 || T
em
:=
make
([]
byte
,
k
);
em
[
1
]
=
1
;
for
i
:=
2
;
i
<
k
-
tLen
-
1
;
i
++
{
em
[
i
]
=
0xff
}
bytes
.
Copy
(
em
[
k
-
tLen
:
k
-
hashLen
],
prefix
);
bytes
.
Copy
(
em
[
k
-
hashLen
:
k
],
hashed
);
m
:=
new
(
big
.
Int
)
.
SetBytes
(
em
);
c
,
err
:=
decrypt
(
rand
,
priv
,
m
);
if
err
==
nil
{
s
=
c
.
Bytes
()
}
return
;
}
// VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
// hashed is the result of hashing the input message using the given hash
// function and sig is the signature. A valid signature is indicated by
// returning a nil error.
func
VerifyPKCS1v15
(
pub
*
PublicKey
,
hash
PKCS1v15Hash
,
hashed
[]
byte
,
sig
[]
byte
)
(
err
os
.
Error
)
{
hashLen
,
prefix
,
err
:=
pkcs1v15HashInfo
(
hash
,
len
(
hashed
));
if
err
!=
nil
{
return
}
tLen
:=
len
(
prefix
)
+
hashLen
;
k
:=
(
pub
.
N
.
Len
()
+
7
)
/
8
;
if
k
<
tLen
+
11
{
err
=
VerificationError
{};
return
;
}
c
:=
new
(
big
.
Int
)
.
SetBytes
(
sig
);
m
:=
encrypt
(
new
(
big
.
Int
),
pub
,
c
);
em
:=
leftPad
(
m
.
Bytes
(),
k
);
// EM = 0x00 || 0x01 || PS || 0x00 || T
ok
:=
subtle
.
ConstantTimeByteEq
(
em
[
0
],
0
);
ok
&=
subtle
.
ConstantTimeByteEq
(
em
[
1
],
1
);
ok
&=
subtle
.
ConstantTimeCompare
(
em
[
k
-
hashLen
:
k
],
hashed
);
ok
&=
subtle
.
ConstantTimeCompare
(
em
[
k
-
tLen
:
k
-
hashLen
],
prefix
);
ok
&=
subtle
.
ConstantTimeByteEq
(
em
[
k
-
tLen
-
1
],
0
);
for
i
:=
2
;
i
<
k
-
tLen
-
1
;
i
++
{
ok
&=
subtle
.
ConstantTimeByteEq
(
em
[
i
],
0xff
)
}
if
ok
!=
1
{
return
VerificationError
{}
}
return
nil
;
}
func
pkcs1v15HashInfo
(
hash
PKCS1v15Hash
,
inLen
int
)
(
hashLen
int
,
prefix
[]
byte
,
err
os
.
Error
)
{
switch
hash
{
case
HashMD5
:
hashLen
=
16
case
HashSHA1
:
hashLen
=
20
case
HashSHA256
:
hashLen
=
32
case
HashSHA384
:
hashLen
=
48
case
HashSHA512
:
hashLen
=
64
default
:
return
0
,
nil
,
os
.
ErrorString
(
"unknown hash function"
)
}
if
inLen
!=
hashLen
{
return
0
,
nil
,
os
.
ErrorString
(
"input must be hashed message"
)
}
prefix
=
hashPrefixes
[
int
(
hash
)];
return
;
}
This diff is collapsed.
Click to expand it.
src/pkg/crypto/rsa/pkcs1v15_test.go
+
45
−
0
View file @
a8ba4082
...
...
@@ -7,7 +7,9 @@ package rsa
import
(
"big"
;
"bytes"
;
"crypto/sha1"
;
"encoding/base64"
;
"encoding/hex"
;
"os"
;
"io"
;
"strings"
;
...
...
@@ -154,6 +156,49 @@ func TestNonZeroRandomBytes(t *testing.T) {
}
}
type
signPKCS1v15Test
struct
{
in
,
out
string
;
}
// These vectors have been tested with
// `openssl rsautl -verify -inkey pk -in signature | hexdump -C`
var
signPKCS1v15Tests
=
[]
signPKCS1v15Test
{
signPKCS1v15Test
{
"Test.
\n
"
,
"a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e336ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
},
}
func
TestSignPKCS1v15
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
signPKCS1v15Tests
{
h
:=
sha1
.
New
();
h
.
Write
(
strings
.
Bytes
(
test
.
in
));
digest
:=
h
.
Sum
();
s
,
err
:=
SignPKCS1v15
(
nil
,
rsaPrivateKey
,
HashSHA1
,
digest
);
if
err
!=
nil
{
t
.
Errorf
(
"#%d %s"
,
i
,
err
)
}
expected
,
_
:=
hex
.
DecodeString
(
test
.
out
);
if
bytes
.
Compare
(
s
,
expected
)
!=
0
{
t
.
Errorf
(
"#%d got: %x want: %x"
,
i
,
s
,
expected
)
}
}
}
func
TestVerifyPKCS1v15
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
signPKCS1v15Tests
{
h
:=
sha1
.
New
();
h
.
Write
(
strings
.
Bytes
(
test
.
in
));
digest
:=
h
.
Sum
();
sig
,
_
:=
hex
.
DecodeString
(
test
.
out
);
err
:=
VerifyPKCS1v15
(
&
rsaPrivateKey
.
PublicKey
,
HashSHA1
,
digest
,
sig
);
if
err
!=
nil
{
t
.
Errorf
(
"#%d %s"
,
i
,
err
)
}
}
}
func
bigFromString
(
s
string
)
*
big
.
Int
{
ret
:=
new
(
big
.
Int
);
ret
.
SetString
(
s
,
10
);
...
...
This diff is collapsed.
Click to expand it.
src/pkg/crypto/rsa/rsa.go
+
6
−
0
View file @
a8ba4082
...
...
@@ -288,6 +288,12 @@ type DecryptionError struct{}
func
(
DecryptionError
)
String
()
string
{
return
"RSA decryption error"
}
// A VerificationError represents a failure to verify a signature.
// It is deliberately vague to avoid adaptive attacks.
type
VerificationError
struct
{}
func
(
VerificationError
)
String
()
string
{
return
"RSA verification error"
}
// modInverse returns ia, the inverse of a in the multiplicative group of prime
// order n. It requires that a be a member of the group (i.e. less than n).
func
modInverse
(
a
,
n
*
big
.
Int
)
(
ia
*
big
.
Int
,
ok
bool
)
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment