Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
5c6162cd
Commit
5c6162cd
authored
May 22, 2012
by
Benjamin Black
Committed by
Adam Langley
May 22, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
crypto/x509: Add ECDSA support
R=golang-dev, agl, rsc CC=golang-dev
https://golang.org/cl/6208087
parent
5759c602
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
241 additions
and
14 deletions
+241
-14
src/pkg/crypto/x509/x509.go
src/pkg/crypto/x509/x509.go
+130
-14
src/pkg/crypto/x509/x509_test.go
src/pkg/crypto/x509/x509_test.go
+111
-0
No files found.
src/pkg/crypto/x509/x509.go
View file @
5c6162cd
...
...
@@ -9,6 +9,8 @@ import (
"bytes"
"crypto"
"crypto/dsa"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
"crypto/sha1"
"crypto/x509/pkix"
...
...
@@ -106,6 +108,8 @@ type dsaSignature struct {
R
,
S
*
big
.
Int
}
type
ecdsaSignature
dsaSignature
type
validity
struct
{
NotBefore
,
NotAfter
time
.
Time
}
...
...
@@ -133,6 +137,10 @@ const (
SHA512WithRSA
DSAWithSHA1
DSAWithSHA256
ECDSAWithSHA1
ECDSAWithSHA256
ECDSAWithSHA384
ECDSAWithSHA512
)
type
PublicKeyAlgorithm
int
...
...
@@ -141,6 +149,7 @@ const (
UnknownPublicKeyAlgorithm
PublicKeyAlgorithm
=
iota
RSA
DSA
ECDSA
)
// OIDs for signature algorithms
...
...
@@ -160,6 +169,12 @@ const (
// dsaWithSha1 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 }
//
// RFC 3279 2.2.3 ECDSA Signature Algorithm
//
// ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) ansi-x962(10045)
// signatures(4) ecdsa-with-SHA1(1)}
//
//
// RFC 4055 5 PKCS #1 Version 1.5
//
...
...
@@ -176,6 +191,17 @@ const (
// joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101)
// csor(3) algorithms(4) id-dsa-with-sha2(3) 2}
//
// RFC 5758 3.2 ECDSA Signature Algorithm
//
// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
//
// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
//
// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
var
(
oidSignatureMD2WithRSA
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
113549
,
1
,
1
,
2
}
oidSignatureMD5WithRSA
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
113549
,
1
,
1
,
4
}
...
...
@@ -185,6 +211,10 @@ var (
oidSignatureSHA512WithRSA
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
113549
,
1
,
1
,
13
}
oidSignatureDSAWithSHA1
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
10040
,
4
,
3
}
oidSignatureDSAWithSHA256
=
asn1
.
ObjectIdentifier
{
2
,
16
,
840
,
1
,
101
,
4
,
3
,
2
}
oidSignatureECDSAWithSHA1
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
10045
,
4
,
1
}
oidSignatureECDSAWithSHA256
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
10045
,
4
,
3
,
2
}
oidSignatureECDSAWithSHA384
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
10045
,
4
,
3
,
3
}
oidSignatureECDSAWithSHA512
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
10045
,
4
,
3
,
4
}
)
func
getSignatureAlgorithmFromOID
(
oid
asn1
.
ObjectIdentifier
)
SignatureAlgorithm
{
...
...
@@ -205,6 +235,14 @@ func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm
return
DSAWithSHA1
case
oid
.
Equal
(
oidSignatureDSAWithSHA256
)
:
return
DSAWithSHA256
case
oid
.
Equal
(
oidSignatureECDSAWithSHA1
)
:
return
ECDSAWithSHA1
case
oid
.
Equal
(
oidSignatureECDSAWithSHA256
)
:
return
ECDSAWithSHA256
case
oid
.
Equal
(
oidSignatureECDSAWithSHA384
)
:
return
ECDSAWithSHA384
case
oid
.
Equal
(
oidSignatureECDSAWithSHA512
)
:
return
ECDSAWithSHA512
}
return
UnknownSignatureAlgorithm
}
...
...
@@ -218,9 +256,15 @@ func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm
//
// id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
// x9-57(10040) x9cm(4) 1 }
//
// RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters
//
// id-ecPublicKey OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
var
(
oidPublicKeyRsa
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
113549
,
1
,
1
,
1
}
oidPublicKeyDsa
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
10040
,
4
,
1
}
oidPublicKeyEcdsa
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
10045
,
2
,
1
}
)
func
getPublicKeyAlgorithmFromOID
(
oid
asn1
.
ObjectIdentifier
)
PublicKeyAlgorithm
{
...
...
@@ -229,10 +273,49 @@ func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm
return
RSA
case
oid
.
Equal
(
oidPublicKeyDsa
)
:
return
DSA
case
oid
.
Equal
(
oidPublicKeyEcdsa
)
:
return
ECDSA
}
return
UnknownPublicKeyAlgorithm
}
// RFC 5480, 2.1.1.1. Named Curve
//
// secp224r1 OBJECT IDENTIFIER ::= {
// iso(1) identified-organization(3) certicom(132) curve(0) 33 }
//
// secp256r1 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
// prime(1) 7 }
//
// secp384r1 OBJECT IDENTIFIER ::= {
// iso(1) identified-organization(3) certicom(132) curve(0) 34 }
//
// secp521r1 OBJECT IDENTIFIER ::= {
// iso(1) identified-organization(3) certicom(132) curve(0) 35 }
//
// NB: secp256r1 is equivalent to prime256v1
var
(
oidNamedCurveP224
=
asn1
.
ObjectIdentifier
{
1
,
3
,
132
,
0
,
33
}
oidNamedCurveP256
=
asn1
.
ObjectIdentifier
{
1
,
2
,
840
,
10045
,
3
,
1
,
7
}
oidNamedCurveP384
=
asn1
.
ObjectIdentifier
{
1
,
3
,
132
,
0
,
34
}
oidNamedCurveP521
=
asn1
.
ObjectIdentifier
{
1
,
3
,
132
,
0
,
35
}
)
func
getNamedCurveFromOID
(
oid
asn1
.
ObjectIdentifier
)
elliptic
.
Curve
{
switch
{
case
oid
.
Equal
(
oidNamedCurveP224
)
:
return
elliptic
.
P224
()
case
oid
.
Equal
(
oidNamedCurveP256
)
:
return
elliptic
.
P256
()
case
oid
.
Equal
(
oidNamedCurveP384
)
:
return
elliptic
.
P384
()
case
oid
.
Equal
(
oidNamedCurveP521
)
:
return
elliptic
.
P521
()
}
return
nil
}
// KeyUsage represents the set of actions that are valid for a given key. It's
// a bitmap of the KeyUsage* constants.
type
KeyUsage
int
...
...
@@ -376,13 +459,13 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
var
hashType
crypto
.
Hash
switch
algo
{
case
SHA1WithRSA
,
DSAWithSHA1
:
case
SHA1WithRSA
,
DSAWithSHA1
,
ECDSAWithSHA1
:
hashType
=
crypto
.
SHA1
case
SHA256WithRSA
,
DSAWithSHA256
:
case
SHA256WithRSA
,
DSAWithSHA256
,
ECDSAWithSHA256
:
hashType
=
crypto
.
SHA256
case
SHA384WithRSA
:
case
SHA384WithRSA
,
ECDSAWithSHA384
:
hashType
=
crypto
.
SHA384
case
SHA512WithRSA
:
case
SHA512WithRSA
,
ECDSAWithSHA512
:
hashType
=
crypto
.
SHA512
default
:
return
ErrUnsupportedAlgorithm
...
...
@@ -411,6 +494,18 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
return
errors
.
New
(
"DSA verification failure"
)
}
return
case
*
ecdsa
.
PublicKey
:
ecdsaSig
:=
new
(
ecdsaSignature
)
if
_
,
err
:=
asn1
.
Unmarshal
(
signature
,
ecdsaSig
);
err
!=
nil
{
return
err
}
if
ecdsaSig
.
R
.
Sign
()
<=
0
||
ecdsaSig
.
S
.
Sign
()
<=
0
{
return
errors
.
New
(
"crypto/x509: ECDSA signature contained zero or negative values"
)
}
if
!
ecdsa
.
Verify
(
pub
,
digest
,
ecdsaSig
.
R
,
ecdsaSig
.
S
)
{
return
errors
.
New
(
"crypto/x509: ECDSA verification failure"
)
}
return
}
return
ErrUnsupportedAlgorithm
}
...
...
@@ -489,6 +584,27 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
Y
:
p
,
}
return
pub
,
nil
case
ECDSA
:
paramsData
:=
keyData
.
Algorithm
.
Parameters
.
FullBytes
namedCurveOID
:=
new
(
asn1
.
ObjectIdentifier
)
_
,
err
:=
asn1
.
Unmarshal
(
paramsData
,
namedCurveOID
)
if
err
!=
nil
{
return
nil
,
err
}
namedCurve
:=
getNamedCurveFromOID
(
*
namedCurveOID
)
if
namedCurve
==
nil
{
return
nil
,
errors
.
New
(
"crypto/x509: unsupported elliptic curve"
)
}
x
,
y
:=
elliptic
.
Unmarshal
(
namedCurve
,
asn1Data
)
if
x
==
nil
{
return
nil
,
errors
.
New
(
"crypto/x509: failed to unmarshal elliptic curve point"
)
}
pub
:=
&
ecdsa
.
PublicKey
{
Curve
:
namedCurve
,
X
:
x
,
Y
:
y
,
}
return
pub
,
nil
default
:
return
nil
,
nil
}
...
...
src/pkg/crypto/x509/x509_test.go
View file @
5c6162cd
...
...
@@ -7,8 +7,11 @@ package x509
import
(
"bytes"
"crypto/dsa"
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
_
"crypto/sha256"
_
"crypto/sha512"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/base64"
...
...
@@ -299,6 +302,114 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
}
}
// Self-signed certificate using ECDSA with SHA1 & secp256r1
var
ecdsaSHA1CertPem
=
`
-----BEGIN CERTIFICATE-----
MIICDjCCAbUCCQDF6SfN0nsnrjAJBgcqhkjOPQQBMIGPMQswCQYDVQQGEwJVUzET
MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMG
A1UECgwMR29vZ2xlLCBJbmMuMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIwMjAyMDUw
WhcNMjIwNTE4MjAyMDUwWjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTATBgNVBAoMDEdvb2dsZSwg
SW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAhBgkqhkiG9w0BCQEWFGdv
bGFuZy1kZXZAZ21haWwuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/Wgn
WQDo5+bz71T0327ERgd5SDDXFbXLpzIZDXTkjpe8QTEbsF+ezsQfrekrpDPC4Cd3
P9LY0tG+aI8IyVKdUjAJBgcqhkjOPQQBA0gAMEUCIGlsqMcRqWVIWTD6wXwe6Jk2
DKxL46r/FLgJYnzBEH99AiEA3fBouObsvV1R3oVkb4BQYnD4/4LeId6lAT43YvyV
a/A=
-----END CERTIFICATE-----
`
// Self-signed certificate using ECDSA with SHA256 & secp256r1
var
ecdsaSHA256p256CertPem
=
`
-----BEGIN CERTIFICATE-----
MIICDzCCAbYCCQDlsuMWvgQzhTAKBggqhkjOPQQDAjCBjzELMAkGA1UEBhMCVVMx
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
BgNVBAoMDEdvb2dsZSwgSW5jLjEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20xIzAh
BgkqhkiG9w0BCQEWFGdvbGFuZy1kZXZAZ21haWwuY29tMB4XDTEyMDUyMTAwMTkx
NloXDTIyMDUxOTAwMTkxNlowgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYDVQQKDAxHb29nbGUs
IEluYy4xFzAVBgNVBAMMDnd3dy5nb29nbGUuY29tMSMwIQYJKoZIhvcNAQkBFhRn
b2xhbmctZGV2QGdtYWlsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPMt
2ErhxAty5EJRu9yM+MTy+hUXm3pdW1ensAv382KoGExSXAFWP7pjJnNtHO+XSwVm
YNtqjcAGFKpweoN//kQwCgYIKoZIzj0EAwIDRwAwRAIgIYSaUA/IB81gjbIw/hUV
70twxJr5EcgOo0hLp3Jm+EYCIFDO3NNcgmURbJ1kfoS3N/0O+irUtoPw38YoNkqJ
h5wi
-----END CERTIFICATE-----
`
// Self-signed certificate using ECDSA with SHA256 & secp384r1
var
ecdsaSHA256p384CertPem
=
`
-----BEGIN CERTIFICATE-----
MIICSjCCAdECCQDje/no7mXkVzAKBggqhkjOPQQDAjCBjjELMAkGA1UEBhMCVVMx
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMDYxMDM0
WhcNMjIwNTE5MDYxMDM0WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
YW5nLWRldkBnbWFpbC5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARRuzRNIKRK
jIktEmXanNmrTR/q/FaHXLhWRZ6nHWe26Fw7Rsrbk+VjGy4vfWtNn7xSFKrOu5ze
qxKnmE0h5E480MNgrUiRkaGO2GMJJVmxx20aqkXOk59U8yGA4CghE6MwCgYIKoZI
zj0EAwIDZwAwZAIwBZEN8gvmRmfeP/9C1PRLzODIY4JqWub2PLRT4mv9GU+yw3Gr
PU9A3CHMdEcdw/MEAjBBO1lId8KOCh9UZunsSMfqXiVurpzmhWd6VYZ/32G+M+Mh
3yILeYQzllt/g0rKVRk=
-----END CERTIFICATE-----
`
// Self-signed certificate using ECDSA with SHA384 & secp521r1
var
ecdsaSHA384p521CertPem
=
`
-----BEGIN CERTIFICATE-----
MIICljCCAfcCCQDhp1AFD/ahKjAKBggqhkjOPQQDAzCBjjELMAkGA1UEBhMCVVMx
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
BgNVBAoMC0dvb2dsZSwgSW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEG
CSqGSIb3DQEJARYUZ29sYW5nLWRldkBnbWFpbC5jb20wHhcNMTIwNTIxMTUwNDI5
WhcNMjIwNTE5MTUwNDI5WjCBjjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlm
b3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSwg
SW5jMRcwFQYDVQQDDA53d3cuZ29vZ2xlLmNvbTEjMCEGCSqGSIb3DQEJARYUZ29s
YW5nLWRldkBnbWFpbC5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACqx9Rv
IssRs1LWYcNN+WffwlHw4Tv3y8/LIAA9MF1ZScIonU9nRMxt4a2uGJVCPDw6JHpz
PaYc0E9puLoE9AfKpwFr59Jkot7dBg55SKPEFkddoip/rvmN7NPAWjMBirOwjOkm
8FPthvPhGPqsu9AvgVuHu3PosWiHGNrhh379pva8MzAKBggqhkjOPQQDAwOBjAAw
gYgCQgEHNmswkUdPpHqrVxp9PvLVl+xxPuHBkT+75z9JizyxtqykHQo9Uh6SWCYH
BF9KLolo01wMt8DjoYP5Fb3j5MH7xwJCAbWZzTOp4l4DPkIvAh4LeC4VWbwPPyqh
kBg71w/iEcSY3wUKgHGcJJrObZw7wys91I5kENljqw/Samdr3ka+jBJa
-----END CERTIFICATE-----
`
var
ecdsaTests
=
[]
struct
{
sigAlgo
SignatureAlgorithm
pemCert
string
}{
{
ECDSAWithSHA1
,
ecdsaSHA1CertPem
},
{
ECDSAWithSHA256
,
ecdsaSHA256p256CertPem
},
{
ECDSAWithSHA256
,
ecdsaSHA256p384CertPem
},
{
ECDSAWithSHA384
,
ecdsaSHA384p521CertPem
},
}
func
TestECDSA
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
ecdsaTests
{
pemBlock
,
_
:=
pem
.
Decode
([]
byte
(
test
.
pemCert
))
cert
,
err
:=
ParseCertificate
(
pemBlock
.
Bytes
)
if
err
!=
nil
{
t
.
Errorf
(
"%d: failed to parse certificate: %s"
,
i
,
err
)
continue
}
if
sa
:=
cert
.
SignatureAlgorithm
;
sa
!=
test
.
sigAlgo
{
t
.
Errorf
(
"%d: signature algorithm is %v, want %v"
,
i
,
sa
,
test
.
sigAlgo
)
}
if
parsedKey
,
ok
:=
cert
.
PublicKey
.
(
*
ecdsa
.
PublicKey
);
!
ok
{
t
.
Errorf
(
"%d: wanted an ECDSA public key but found: %#v"
,
i
,
parsedKey
)
}
if
pka
:=
cert
.
PublicKeyAlgorithm
;
pka
!=
ECDSA
{
t
.
Errorf
(
"%d: public key algorithm is %v, want ECDSA"
,
i
,
pka
)
}
if
err
=
cert
.
CheckSignatureFrom
(
cert
);
err
!=
nil
{
t
.
Errorf
(
"%d: certificate verfication failed: %s"
,
i
,
err
)
}
}
}
// Self-signed certificate using DSA with SHA1
var
dsaCertPem
=
`-----BEGIN CERTIFICATE-----
MIIEDTCCA82gAwIBAgIJALHPghaoxeDhMAkGByqGSM44BAMweTELMAkGA1UEBhMC
...
...
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