Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
caddy
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
nexedi
caddy
Commits
9e386fc9
Commit
9e386fc9
authored
Mar 03, 2016
by
Matt Holt
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #652 from elcore/patch-2
https: Support ECC keys
parents
36b440c0
9099375b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
102 additions
and
51 deletions
+102
-51
caddy/https/client.go
caddy/https/client.go
+1
-10
caddy/https/crypto.go
caddy/https/crypto.go
+32
-6
caddy/https/crypto_test.go
caddy/https/crypto_test.go
+60
-16
caddy/https/https.go
caddy/https/https.go
+2
-13
caddy/https/user.go
caddy/https/user.go
+6
-5
caddy/https/user_test.go
caddy/https/user_test.go
+1
-1
No files found.
caddy/https/client.go
View file @
9e386fc9
...
...
@@ -34,16 +34,7 @@ var NewACMEClient = func(email string, allowPrompts bool) (*ACMEClient, error) {
}
// The client facilitates our communication with the CA server.
var
kt
acme
.
KeyType
if
rsaKeySizeToUse
==
Rsa2048
{
kt
=
acme
.
RSA2048
}
else
if
rsaKeySizeToUse
==
Rsa4096
{
kt
=
acme
.
RSA4096
}
else
{
// TODO(hkjn): Support more types? Current changes are quick fix for #640.
return
nil
,
fmt
.
Errorf
(
"https: unsupported keysize"
)
}
client
,
err
:=
acme
.
NewClient
(
CAUrl
,
&
leUser
,
kt
)
client
,
err
:=
acme
.
NewClient
(
CAUrl
,
&
leUser
,
KeyType
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
caddy/https/crypto.go
View file @
9e386fc9
package
https
import
(
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"io/ioutil"
"os"
)
// load
RSAPrivateKey loads a PEM-encoded
RSA private key from file.
func
load
RSAPrivateKey
(
file
string
)
(
*
rsa
.
PrivateKey
,
error
)
{
// load
PrivateKey loads a PEM-encoded ECC/
RSA private key from file.
func
load
PrivateKey
(
file
string
)
(
crypto
.
PrivateKey
,
error
)
{
keyBytes
,
err
:=
ioutil
.
ReadFile
(
file
)
if
err
!=
nil
{
return
nil
,
err
}
keyBlock
,
_
:=
pem
.
Decode
(
keyBytes
)
return
x509
.
ParsePKCS1PrivateKey
(
keyBlock
.
Bytes
)
switch
keyBlock
.
Type
{
case
"RSA PRIVATE KEY"
:
return
x509
.
ParsePKCS1PrivateKey
(
keyBlock
.
Bytes
)
case
"EC PRIVATE KEY"
:
return
x509
.
ParseECPrivateKey
(
keyBlock
.
Bytes
)
}
return
nil
,
errors
.
New
(
"unknown private key type"
)
}
// saveRSAPrivateKey saves a PEM-encoded RSA private key to file.
func
saveRSAPrivateKey
(
key
*
rsa
.
PrivateKey
,
file
string
)
error
{
pemKey
:=
pem
.
Block
{
Type
:
"RSA PRIVATE KEY"
,
Bytes
:
x509
.
MarshalPKCS1PrivateKey
(
key
)}
// savePrivateKey saves a PEM-encoded ECC/RSA private key to file.
func
savePrivateKey
(
key
crypto
.
PrivateKey
,
file
string
)
error
{
var
pemType
string
var
keyBytes
[]
byte
switch
key
:=
key
.
(
type
)
{
case
*
ecdsa
.
PrivateKey
:
var
err
error
pemType
=
"EC"
keyBytes
,
err
=
x509
.
MarshalECPrivateKey
(
key
)
if
err
!=
nil
{
return
err
}
case
*
rsa
.
PrivateKey
:
pemType
=
"RSA"
keyBytes
=
x509
.
MarshalPKCS1PrivateKey
(
key
)
}
pemKey
:=
pem
.
Block
{
Type
:
pemType
+
" PRIVATE KEY"
,
Bytes
:
keyBytes
}
keyOut
,
err
:=
os
.
Create
(
file
)
if
err
!=
nil
{
return
err
...
...
caddy/https/crypto_test.go
View file @
9e386fc9
...
...
@@ -2,6 +2,9 @@ package https
import
(
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
...
...
@@ -10,23 +13,17 @@ import (
"testing"
)
func
init
()
{
rsaKeySizeToUse
=
2048
// TODO(hkjn): Bring back support for small
// keys to speed up tests? Current changes
// are quick fix for #640.
}
func
TestSaveAndLoadRSAPrivateKey
(
t
*
testing
.
T
)
{
keyFile
:=
"test.key"
defer
os
.
Remove
(
keyFile
)
privateKey
,
err
:=
rsa
.
GenerateKey
(
rand
.
Reader
,
rsaKeySizeToUse
)
privateKey
,
err
:=
rsa
.
GenerateKey
(
rand
.
Reader
,
2048
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// test save
err
=
save
RSA
PrivateKey
(
privateKey
,
keyFile
)
err
=
savePrivateKey
(
privateKey
,
keyFile
)
if
err
!=
nil
{
t
.
Fatal
(
"error saving private key:"
,
err
)
}
...
...
@@ -45,23 +42,70 @@ func TestSaveAndLoadRSAPrivateKey(t *testing.T) {
}
// test load
loadedKey
,
err
:=
load
RSA
PrivateKey
(
keyFile
)
loadedKey
,
err
:=
loadPrivateKey
(
keyFile
)
if
err
!=
nil
{
t
.
Error
(
"error loading private key:"
,
err
)
}
// verify loaded key is correct
if
!
rsa
PrivateKeysSame
(
privateKey
,
loadedKey
)
{
if
!
PrivateKeysSame
(
privateKey
,
loadedKey
)
{
t
.
Error
(
"Expected key bytes to be the same, but they weren't"
)
}
}
// rsaPrivateKeysSame compares the bytes of a and b and returns true if they are the same.
func
rsaPrivateKeysSame
(
a
,
b
*
rsa
.
PrivateKey
)
bool
{
return
bytes
.
Equal
(
rsaPrivateKeyBytes
(
a
),
rsaPrivateKeyBytes
(
b
))
func
TestSaveAndLoadECCPrivateKey
(
t
*
testing
.
T
)
{
keyFile
:=
"test.key"
defer
os
.
Remove
(
keyFile
)
privateKey
,
err
:=
ecdsa
.
GenerateKey
(
elliptic
.
P384
(),
rand
.
Reader
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// test save
err
=
savePrivateKey
(
privateKey
,
keyFile
)
if
err
!=
nil
{
t
.
Fatal
(
"error saving private key:"
,
err
)
}
// it doesn't make sense to test file permission on windows
if
runtime
.
GOOS
!=
"windows"
{
// get info of the key file
info
,
err
:=
os
.
Stat
(
keyFile
)
if
err
!=
nil
{
t
.
Fatal
(
"error stating private key:"
,
err
)
}
// verify permission of key file is correct
if
info
.
Mode
()
.
Perm
()
!=
0600
{
t
.
Error
(
"Expected key file to have permission 0600, but it wasn't"
)
}
}
// test load
loadedKey
,
err
:=
loadPrivateKey
(
keyFile
)
if
err
!=
nil
{
t
.
Error
(
"error loading private key:"
,
err
)
}
// verify loaded key is correct
if
!
PrivateKeysSame
(
privateKey
,
loadedKey
)
{
t
.
Error
(
"Expected key bytes to be the same, but they weren't"
)
}
}
// PrivateKeysSame compares the bytes of a and b and returns true if they are the same.
func
PrivateKeysSame
(
a
,
b
crypto
.
PrivateKey
)
bool
{
return
bytes
.
Equal
(
PrivateKeyBytes
(
a
),
PrivateKeyBytes
(
b
))
}
// rsaPrivateKeyBytes returns the bytes of DER-encoded key.
func
rsaPrivateKeyBytes
(
key
*
rsa
.
PrivateKey
)
[]
byte
{
return
x509
.
MarshalPKCS1PrivateKey
(
key
)
// PrivateKeyBytes returns the bytes of DER-encoded key.
func
PrivateKeyBytes
(
key
crypto
.
PrivateKey
)
[]
byte
{
var
keyBytes
[]
byte
switch
key
:=
key
.
(
type
)
{
case
*
rsa
.
PrivateKey
:
keyBytes
=
x509
.
MarshalPKCS1PrivateKey
(
key
)
case
*
ecdsa
.
PrivateKey
:
keyBytes
,
_
=
x509
.
MarshalECPrivateKey
(
key
)
}
return
keyBytes
}
caddy/https/https.go
View file @
9e386fc9
...
...
@@ -401,21 +401,10 @@ var (
// default port for the challenge must be forwarded to this one.
const
AlternatePort
=
"5033"
// KeySize represents the length of a key in bits.
type
KeySize
int
// Key sizes are used to determine the strength of a key.
const
(
Ecc224
KeySize
=
224
Ecc256
=
256
Rsa2048
=
2048
Rsa4096
=
4096
)
// rsaKeySizeToUse is the size to use for new RSA keys.
// KeyType is the type to use for new keys.
// This shouldn't need to change except for in tests;
// the size can be drastically reduced for speed.
var
rsaKeySizeToUse
=
Rsa2048
var
KeyType
=
acme
.
EC384
// stopChan is used to signal the maintenance goroutine
// to terminate.
...
...
caddy/https/user.go
View file @
9e386fc9
...
...
@@ -3,8 +3,9 @@ package https
import
(
"bufio"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"encoding/json"
"errors"
"fmt"
...
...
@@ -21,7 +22,7 @@ import (
type
User
struct
{
Email
string
Registration
*
acme
.
RegistrationResource
key
*
rsa
.
PrivateKey
key
crypto
.
PrivateKey
}
// GetEmail gets u's email.
...
...
@@ -64,7 +65,7 @@ func getUser(email string) (User, error) {
}
// load their private key
user
.
key
,
err
=
load
RSA
PrivateKey
(
storage
.
UserKeyFile
(
email
))
user
.
key
,
err
=
loadPrivateKey
(
storage
.
UserKeyFile
(
email
))
if
err
!=
nil
{
return
user
,
err
}
...
...
@@ -83,7 +84,7 @@ func saveUser(user User) error {
}
// save private key file
err
=
save
RSA
PrivateKey
(
user
.
key
,
storage
.
UserKeyFile
(
user
.
Email
))
err
=
savePrivateKey
(
user
.
key
,
storage
.
UserKeyFile
(
user
.
Email
))
if
err
!=
nil
{
return
err
}
...
...
@@ -104,7 +105,7 @@ func saveUser(user User) error {
// instead. It does NOT prompt the user.
func
newUser
(
email
string
)
(
User
,
error
)
{
user
:=
User
{
Email
:
email
}
privateKey
,
err
:=
rsa
.
GenerateKey
(
rand
.
Reader
,
rsaKeySizeToUse
)
privateKey
,
err
:=
ecdsa
.
GenerateKey
(
elliptic
.
P384
(),
rand
.
Reader
)
if
err
!=
nil
{
return
user
,
errors
.
New
(
"error generating private key: "
+
err
.
Error
())
}
...
...
caddy/https/user_test.go
View file @
9e386fc9
...
...
@@ -114,7 +114,7 @@ func TestGetUserAlreadyExists(t *testing.T) {
}
// Assert keys are the same
if
!
rsa
PrivateKeysSame
(
user
.
key
,
user2
.
key
)
{
if
!
PrivateKeysSame
(
user
.
key
,
user2
.
key
)
{
t
.
Error
(
"Expected private key to be the same after loading, but it wasn't"
)
}
...
...
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