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
Show 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) {
...
@@ -34,16 +34,7 @@ var NewACMEClient = func(email string, allowPrompts bool) (*ACMEClient, error) {
}
}
// The client facilitates our communication with the CA server.
// The client facilitates our communication with the CA server.
var
kt
acme
.
KeyType
client
,
err
:=
acme
.
NewClient
(
CAUrl
,
&
leUser
,
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
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
...
caddy/https/crypto.go
View file @
9e386fc9
package
https
package
https
import
(
import
(
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/rsa"
"crypto/x509"
"crypto/x509"
"encoding/pem"
"encoding/pem"
"errors"
"io/ioutil"
"io/ioutil"
"os"
"os"
)
)
// load
RSAPrivateKey loads a PEM-encoded
RSA private key from file.
// load
PrivateKey loads a PEM-encoded ECC/
RSA private key from file.
func
load
RSAPrivateKey
(
file
string
)
(
*
rsa
.
PrivateKey
,
error
)
{
func
load
PrivateKey
(
file
string
)
(
crypto
.
PrivateKey
,
error
)
{
keyBytes
,
err
:=
ioutil
.
ReadFile
(
file
)
keyBytes
,
err
:=
ioutil
.
ReadFile
(
file
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
keyBlock
,
_
:=
pem
.
Decode
(
keyBytes
)
keyBlock
,
_
:=
pem
.
Decode
(
keyBytes
)
switch
keyBlock
.
Type
{
case
"RSA PRIVATE KEY"
:
return
x509
.
ParsePKCS1PrivateKey
(
keyBlock
.
Bytes
)
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.
// savePrivateKey saves a PEM-encoded ECC/RSA private key to file.
func
saveRSAPrivateKey
(
key
*
rsa
.
PrivateKey
,
file
string
)
error
{
func
savePrivateKey
(
key
crypto
.
PrivateKey
,
file
string
)
error
{
pemKey
:=
pem
.
Block
{
Type
:
"RSA PRIVATE KEY"
,
Bytes
:
x509
.
MarshalPKCS1PrivateKey
(
key
)}
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
)
keyOut
,
err
:=
os
.
Create
(
file
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
...
caddy/https/crypto_test.go
View file @
9e386fc9
...
@@ -2,6 +2,9 @@ package https
...
@@ -2,6 +2,9 @@ package https
import
(
import
(
"bytes"
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rand"
"crypto/rsa"
"crypto/rsa"
"crypto/x509"
"crypto/x509"
...
@@ -10,23 +13,57 @@ import (
...
@@ -10,23 +13,57 @@ import (
"testing"
"testing"
)
)
func
init
()
{
func
TestSaveAndLoadRSAPrivateKey
(
t
*
testing
.
T
)
{
rsaKeySizeToUse
=
2048
// TODO(hkjn): Bring back support for small
keyFile
:=
"test.key"
// keys to speed up tests? Current changes
defer
os
.
Remove
(
keyFile
)
// are quick fix for #640.
privateKey
,
err
:=
rsa
.
GenerateKey
(
rand
.
Reader
,
2048
)
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"
)
}
}
}
func
TestSaveAndLoad
RSA
PrivateKey
(
t
*
testing
.
T
)
{
func
TestSaveAndLoad
ECC
PrivateKey
(
t
*
testing
.
T
)
{
keyFile
:=
"test.key"
keyFile
:=
"test.key"
defer
os
.
Remove
(
keyFile
)
defer
os
.
Remove
(
keyFile
)
privateKey
,
err
:=
rsa
.
GenerateKey
(
rand
.
Reader
,
rsaKeySizeToUse
)
privateKey
,
err
:=
ecdsa
.
GenerateKey
(
elliptic
.
P384
(),
rand
.
Reader
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
// test save
// test save
err
=
save
RSA
PrivateKey
(
privateKey
,
keyFile
)
err
=
savePrivateKey
(
privateKey
,
keyFile
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
"error saving private key:"
,
err
)
t
.
Fatal
(
"error saving private key:"
,
err
)
}
}
...
@@ -45,23 +82,30 @@ func TestSaveAndLoadRSAPrivateKey(t *testing.T) {
...
@@ -45,23 +82,30 @@ func TestSaveAndLoadRSAPrivateKey(t *testing.T) {
}
}
// test load
// test load
loadedKey
,
err
:=
load
RSA
PrivateKey
(
keyFile
)
loadedKey
,
err
:=
loadPrivateKey
(
keyFile
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
(
"error loading private key:"
,
err
)
t
.
Error
(
"error loading private key:"
,
err
)
}
}
// verify loaded key is correct
// 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"
)
t
.
Error
(
"Expected key bytes to be the same, but they weren't"
)
}
}
}
}
//
rsa
PrivateKeysSame compares the bytes of a and b and returns true if they are the same.
// PrivateKeysSame compares the bytes of a and b and returns true if they are the same.
func
rsaPrivateKeysSame
(
a
,
b
*
rsa
.
PrivateKey
)
bool
{
func
PrivateKeysSame
(
a
,
b
crypto
.
PrivateKey
)
bool
{
return
bytes
.
Equal
(
rsaPrivateKeyBytes
(
a
),
rsa
PrivateKeyBytes
(
b
))
return
bytes
.
Equal
(
PrivateKeyBytes
(
a
),
PrivateKeyBytes
(
b
))
}
}
// rsaPrivateKeyBytes returns the bytes of DER-encoded key.
// PrivateKeyBytes returns the bytes of DER-encoded key.
func
rsaPrivateKeyBytes
(
key
*
rsa
.
PrivateKey
)
[]
byte
{
func
PrivateKeyBytes
(
key
crypto
.
PrivateKey
)
[]
byte
{
return
x509
.
MarshalPKCS1PrivateKey
(
key
)
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 (
...
@@ -401,21 +401,10 @@ var (
// default port for the challenge must be forwarded to this one.
// default port for the challenge must be forwarded to this one.
const
AlternatePort
=
"5033"
const
AlternatePort
=
"5033"
// KeySize represents the length of a key in bits.
// KeyType is the type to use for new keys.
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.
// This shouldn't need to change except for in tests;
// This shouldn't need to change except for in tests;
// the size can be drastically reduced for speed.
// the size can be drastically reduced for speed.
var
rsaKeySizeToUse
=
Rsa2048
var
KeyType
=
acme
.
EC384
// stopChan is used to signal the maintenance goroutine
// stopChan is used to signal the maintenance goroutine
// to terminate.
// to terminate.
...
...
caddy/https/user.go
View file @
9e386fc9
...
@@ -3,8 +3,9 @@ package https
...
@@ -3,8 +3,9 @@ package https
import
(
import
(
"bufio"
"bufio"
"crypto"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rand"
"crypto/rsa"
"encoding/json"
"encoding/json"
"errors"
"errors"
"fmt"
"fmt"
...
@@ -21,7 +22,7 @@ import (
...
@@ -21,7 +22,7 @@ import (
type
User
struct
{
type
User
struct
{
Email
string
Email
string
Registration
*
acme
.
RegistrationResource
Registration
*
acme
.
RegistrationResource
key
*
rsa
.
PrivateKey
key
crypto
.
PrivateKey
}
}
// GetEmail gets u's email.
// GetEmail gets u's email.
...
@@ -64,7 +65,7 @@ func getUser(email string) (User, error) {
...
@@ -64,7 +65,7 @@ func getUser(email string) (User, error) {
}
}
// load their private key
// load their private key
user
.
key
,
err
=
load
RSA
PrivateKey
(
storage
.
UserKeyFile
(
email
))
user
.
key
,
err
=
loadPrivateKey
(
storage
.
UserKeyFile
(
email
))
if
err
!=
nil
{
if
err
!=
nil
{
return
user
,
err
return
user
,
err
}
}
...
@@ -83,7 +84,7 @@ func saveUser(user User) error {
...
@@ -83,7 +84,7 @@ func saveUser(user User) error {
}
}
// save private key file
// 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
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -104,7 +105,7 @@ func saveUser(user User) error {
...
@@ -104,7 +105,7 @@ func saveUser(user User) error {
// instead. It does NOT prompt the user.
// instead. It does NOT prompt the user.
func
newUser
(
email
string
)
(
User
,
error
)
{
func
newUser
(
email
string
)
(
User
,
error
)
{
user
:=
User
{
Email
:
email
}
user
:=
User
{
Email
:
email
}
privateKey
,
err
:=
rsa
.
GenerateKey
(
rand
.
Reader
,
rsaKeySizeToUse
)
privateKey
,
err
:=
ecdsa
.
GenerateKey
(
elliptic
.
P384
(),
rand
.
Reader
)
if
err
!=
nil
{
if
err
!=
nil
{
return
user
,
errors
.
New
(
"error generating private key: "
+
err
.
Error
())
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) {
...
@@ -114,7 +114,7 @@ func TestGetUserAlreadyExists(t *testing.T) {
}
}
// Assert keys are the same
// 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"
)
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