forked from cerc-io/plugeth
commit
c1d0693cb1
46
Godeps/Godeps.json
generated
46
Godeps/Godeps.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ImportPath": "github.com/ethereum/go-ethereum",
|
"ImportPath": "github.com/ethereum/go-ethereum",
|
||||||
"GoVersion": "go1.4",
|
"GoVersion": "go1.4.1",
|
||||||
"Packages": [
|
"Packages": [
|
||||||
"./..."
|
"./..."
|
||||||
],
|
],
|
||||||
@ -15,26 +15,6 @@
|
|||||||
"Comment": "null-12",
|
"Comment": "null-12",
|
||||||
"Rev": "7dda39b2e7d5e265014674c5af696ba4186679e9"
|
"Rev": "7dda39b2e7d5e265014674c5af696ba4186679e9"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ImportPath": "code.google.com/p/go.crypto/pbkdf2",
|
|
||||||
"Comment": "null-236",
|
|
||||||
"Rev": "69e2a90ed92d03812364aeb947b7068dc42e561e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "code.google.com/p/go.crypto/ripemd160",
|
|
||||||
"Comment": "null-236",
|
|
||||||
"Rev": "69e2a90ed92d03812364aeb947b7068dc42e561e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "code.google.com/p/go.crypto/scrypt",
|
|
||||||
"Comment": "null-236",
|
|
||||||
"Rev": "69e2a90ed92d03812364aeb947b7068dc42e561e"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "code.google.com/p/go.net/websocket",
|
|
||||||
"Comment": "null-173",
|
|
||||||
"Rev": "4231557d7c726df4cf9a4e8cdd8a417c8c200bdb"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ImportPath": "code.google.com/p/snappy-go/snappy",
|
"ImportPath": "code.google.com/p/snappy-go/snappy",
|
||||||
"Comment": "null-15",
|
"Comment": "null-15",
|
||||||
@ -44,22 +24,18 @@
|
|||||||
"ImportPath": "github.com/ethereum/serpent-go",
|
"ImportPath": "github.com/ethereum/serpent-go",
|
||||||
"Rev": "5767a0dbd759d313df3f404dadb7f98d7ab51443"
|
"Rev": "5767a0dbd759d313df3f404dadb7f98d7ab51443"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ImportPath": "github.com/fjl/goupnp",
|
|
||||||
"Rev": "fa95df6feb61e136b499d01711fcd410ccaf20c1"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/howeyc/fsnotify",
|
"ImportPath": "github.com/howeyc/fsnotify",
|
||||||
"Comment": "v0.9.0-11-g6b1ef89",
|
"Comment": "v0.9.0-11-g6b1ef89",
|
||||||
"Rev": "6b1ef893dc11e0447abda6da20a5203481878dda"
|
"Rev": "6b1ef893dc11e0447abda6da20a5203481878dda"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/jackpal/go-nat-pmp",
|
"ImportPath": "github.com/huin/goupnp",
|
||||||
"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
|
"Rev": "4191d8a85005844ea202fde52799681971b12dfe"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/obscuren/ecies",
|
"ImportPath": "github.com/jackpal/go-nat-pmp",
|
||||||
"Rev": "d899334bba7bf4a157cab19d8ad836dcb1de0c34"
|
"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/obscuren/otto",
|
"ImportPath": "github.com/obscuren/otto",
|
||||||
@ -109,6 +85,18 @@
|
|||||||
"ImportPath": "golang.org/x/crypto/pbkdf2",
|
"ImportPath": "golang.org/x/crypto/pbkdf2",
|
||||||
"Rev": "4ed45ec682102c643324fae5dff8dab085b6c300"
|
"Rev": "4ed45ec682102c643324fae5dff8dab085b6c300"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/ripemd160",
|
||||||
|
"Rev": "4ed45ec682102c643324fae5dff8dab085b6c300"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/scrypt",
|
||||||
|
"Rev": "4ed45ec682102c643324fae5dff8dab085b6c300"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/net/websocket",
|
||||||
|
"Rev": "59b0df9b1f7abda5aab0495ee54f408daf182ce7"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "gopkg.in/check.v1",
|
"ImportPath": "gopkg.in/check.v1",
|
||||||
"Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673"
|
"Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673"
|
||||||
|
77
Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go
generated
vendored
77
Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go
generated
vendored
@ -1,77 +0,0 @@
|
|||||||
// Copyright 2012 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 pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
|
|
||||||
2898 / PKCS #5 v2.0.
|
|
||||||
|
|
||||||
A key derivation function is useful when encrypting data based on a password
|
|
||||||
or any other not-fully-random data. It uses a pseudorandom function to derive
|
|
||||||
a secure encryption key based on the password.
|
|
||||||
|
|
||||||
While v2.0 of the standard defines only one pseudorandom function to use,
|
|
||||||
HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
|
|
||||||
Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
|
|
||||||
choose, you can pass the `New` functions from the different SHA packages to
|
|
||||||
pbkdf2.Key.
|
|
||||||
*/
|
|
||||||
package pbkdf2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/hmac"
|
|
||||||
"hash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Key derives a key from the password, salt and iteration count, returning a
|
|
||||||
// []byte of length keylen that can be used as cryptographic key. The key is
|
|
||||||
// derived based on the method described as PBKDF2 with the HMAC variant using
|
|
||||||
// the supplied hash function.
|
|
||||||
//
|
|
||||||
// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
|
|
||||||
// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
|
|
||||||
// doing:
|
|
||||||
//
|
|
||||||
// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
|
|
||||||
//
|
|
||||||
// Remember to get a good random salt. At least 8 bytes is recommended by the
|
|
||||||
// RFC.
|
|
||||||
//
|
|
||||||
// Using a higher iteration count will increase the cost of an exhaustive
|
|
||||||
// search but will also make derivation proportionally slower.
|
|
||||||
func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
|
|
||||||
prf := hmac.New(h, password)
|
|
||||||
hashLen := prf.Size()
|
|
||||||
numBlocks := (keyLen + hashLen - 1) / hashLen
|
|
||||||
|
|
||||||
var buf [4]byte
|
|
||||||
dk := make([]byte, 0, numBlocks*hashLen)
|
|
||||||
U := make([]byte, hashLen)
|
|
||||||
for block := 1; block <= numBlocks; block++ {
|
|
||||||
// N.B.: || means concatenation, ^ means XOR
|
|
||||||
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
|
|
||||||
// U_1 = PRF(password, salt || uint(i))
|
|
||||||
prf.Reset()
|
|
||||||
prf.Write(salt)
|
|
||||||
buf[0] = byte(block >> 24)
|
|
||||||
buf[1] = byte(block >> 16)
|
|
||||||
buf[2] = byte(block >> 8)
|
|
||||||
buf[3] = byte(block)
|
|
||||||
prf.Write(buf[:4])
|
|
||||||
dk = prf.Sum(dk)
|
|
||||||
T := dk[len(dk)-hashLen:]
|
|
||||||
copy(U, T)
|
|
||||||
|
|
||||||
// U_n = PRF(password, U_(n-1))
|
|
||||||
for n := 2; n <= iter; n++ {
|
|
||||||
prf.Reset()
|
|
||||||
prf.Write(U)
|
|
||||||
U = U[:0]
|
|
||||||
U = prf.Sum(U)
|
|
||||||
for x := range U {
|
|
||||||
T[x] ^= U[x]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dk[:keyLen]
|
|
||||||
}
|
|
157
Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go
generated
vendored
157
Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go
generated
vendored
@ -1,157 +0,0 @@
|
|||||||
// Copyright 2012 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 pbkdf2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/sha256"
|
|
||||||
"hash"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type testVector struct {
|
|
||||||
password string
|
|
||||||
salt string
|
|
||||||
iter int
|
|
||||||
output []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070
|
|
||||||
var sha1TestVectors = []testVector{
|
|
||||||
{
|
|
||||||
"password",
|
|
||||||
"salt",
|
|
||||||
1,
|
|
||||||
[]byte{
|
|
||||||
0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
|
|
||||||
0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
|
|
||||||
0x2f, 0xe0, 0x37, 0xa6,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"password",
|
|
||||||
"salt",
|
|
||||||
2,
|
|
||||||
[]byte{
|
|
||||||
0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
|
|
||||||
0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
|
|
||||||
0xd8, 0xde, 0x89, 0x57,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"password",
|
|
||||||
"salt",
|
|
||||||
4096,
|
|
||||||
[]byte{
|
|
||||||
0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
|
|
||||||
0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
|
|
||||||
0x65, 0xa4, 0x29, 0xc1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// // This one takes too long
|
|
||||||
// {
|
|
||||||
// "password",
|
|
||||||
// "salt",
|
|
||||||
// 16777216,
|
|
||||||
// []byte{
|
|
||||||
// 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
|
|
||||||
// 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
|
|
||||||
// 0x26, 0x34, 0xe9, 0x84,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
"passwordPASSWORDpassword",
|
|
||||||
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
|
|
||||||
4096,
|
|
||||||
[]byte{
|
|
||||||
0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
|
|
||||||
0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
|
|
||||||
0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
|
|
||||||
0x38,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pass\000word",
|
|
||||||
"sa\000lt",
|
|
||||||
4096,
|
|
||||||
[]byte{
|
|
||||||
0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
|
|
||||||
0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test vectors from
|
|
||||||
// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors
|
|
||||||
var sha256TestVectors = []testVector{
|
|
||||||
{
|
|
||||||
"password",
|
|
||||||
"salt",
|
|
||||||
1,
|
|
||||||
[]byte{
|
|
||||||
0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c,
|
|
||||||
0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37,
|
|
||||||
0xa8, 0x65, 0x48, 0xc9,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"password",
|
|
||||||
"salt",
|
|
||||||
2,
|
|
||||||
[]byte{
|
|
||||||
0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
|
|
||||||
0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
|
|
||||||
0x2a, 0x30, 0x3f, 0x8e,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"password",
|
|
||||||
"salt",
|
|
||||||
4096,
|
|
||||||
[]byte{
|
|
||||||
0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41,
|
|
||||||
0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d,
|
|
||||||
0x96, 0x28, 0x93, 0xa0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"passwordPASSWORDpassword",
|
|
||||||
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
|
|
||||||
4096,
|
|
||||||
[]byte{
|
|
||||||
0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f,
|
|
||||||
0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf,
|
|
||||||
0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18,
|
|
||||||
0x1c,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pass\000word",
|
|
||||||
"sa\000lt",
|
|
||||||
4096,
|
|
||||||
[]byte{
|
|
||||||
0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89,
|
|
||||||
0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) {
|
|
||||||
for i, v := range vectors {
|
|
||||||
o := Key([]byte(v.password), []byte(v.salt), v.iter, len(v.output), h)
|
|
||||||
if !bytes.Equal(o, v.output) {
|
|
||||||
t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithHMACSHA1(t *testing.T) {
|
|
||||||
testHash(t, sha1.New, "SHA1", sha1TestVectors)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithHMACSHA256(t *testing.T) {
|
|
||||||
testHash(t, sha256.New, "SHA256", sha256TestVectors)
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ goupnp is a UPnP client library for Go
|
|||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Run `go get -u github.com/fjl/goupnp`.
|
Run `go get -u github.com/huin/goupnp`.
|
||||||
|
|
||||||
Regenerating dcps generated source code:
|
Regenerating dcps generated source code:
|
||||||
----------------------------------------
|
----------------------------------------
|
@ -4,7 +4,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/fjl/goupnp/httpu"
|
"github.com/huin/goupnp/httpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/fjl/goupnp/dcps/internetgateway1"
|
"github.com/huin/goupnp/dcps/internetgateway1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
@ -11,8 +11,8 @@ package internetgateway1
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fjl/goupnp"
|
"github.com/huin/goupnp"
|
||||||
"github.com/fjl/goupnp/soap"
|
"github.com/huin/goupnp/soap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hack to avoid Go complaining if time isn't used.
|
// Hack to avoid Go complaining if time isn't used.
|
@ -11,8 +11,8 @@ package internetgateway2
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fjl/goupnp"
|
"github.com/huin/goupnp"
|
||||||
"github.com/fjl/goupnp/soap"
|
"github.com/huin/goupnp/soap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hack to avoid Go complaining if time isn't used.
|
// Hack to avoid Go complaining if time isn't used.
|
@ -8,8 +8,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/fjl/goupnp/scpd"
|
"github.com/huin/goupnp/scpd"
|
||||||
"github.com/fjl/goupnp/soap"
|
"github.com/huin/goupnp/soap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
@ -2,5 +2,5 @@
|
|||||||
//
|
//
|
||||||
// To run examples and see the output for your local network, run the following
|
// To run examples and see the output for your local network, run the following
|
||||||
// command (specifically including the -v flag):
|
// command (specifically including the -v flag):
|
||||||
// go test -v github.com/fjl/goupnp/example
|
// go test -v github.com/huin/goupnp/example
|
||||||
package example
|
package example
|
@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/fjl/goupnp"
|
"github.com/huin/goupnp"
|
||||||
"github.com/fjl/goupnp/dcps/internetgateway1"
|
"github.com/huin/goupnp/dcps/internetgateway1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Use discovered WANPPPConnection1 services to find external IP addresses.
|
// Use discovered WANPPPConnection1 services to find external IP addresses.
|
@ -17,8 +17,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/fjl/goupnp"
|
"github.com/huin/goupnp"
|
||||||
"github.com/fjl/goupnp/scpd"
|
"github.com/huin/goupnp/scpd"
|
||||||
"github.com/huin/goutil/codegen"
|
"github.com/huin/goutil/codegen"
|
||||||
"github.com/jingweno/gotask/tasking"
|
"github.com/jingweno/gotask/tasking"
|
||||||
)
|
)
|
||||||
@ -38,7 +38,7 @@ var (
|
|||||||
// -s, --spec_filename=<upnpresources.zip>
|
// -s, --spec_filename=<upnpresources.zip>
|
||||||
// Path to the specification file, available from http://upnp.org/resources/upnpresources.zip
|
// Path to the specification file, available from http://upnp.org/resources/upnpresources.zip
|
||||||
// -o, --out_dir=<output directory>
|
// -o, --out_dir=<output directory>
|
||||||
// Path to the output directory. This is is where the DCP source files will be placed. Should normally correspond to the directory for github.com/fjl/goupnp/dcps
|
// Path to the output directory. This is is where the DCP source files will be placed. Should normally correspond to the directory for github.com/huin/goupnp/dcps
|
||||||
// --nogofmt
|
// --nogofmt
|
||||||
// Disable passing the output through gofmt. Do this if debugging code output problems and needing to see the generated code prior to being passed through gofmt.
|
// Disable passing the output through gofmt. Do this if debugging code output problems and needing to see the generated code prior to being passed through gofmt.
|
||||||
func TaskSpecgen(t *tasking.T) {
|
func TaskSpecgen(t *tasking.T) {
|
||||||
@ -445,8 +445,8 @@ package {{$name}}
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fjl/goupnp"
|
"github.com/huin/goupnp"
|
||||||
"github.com/fjl/goupnp/soap"
|
"github.com/huin/goupnp/soap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hack to avoid Go complaining if time isn't used.
|
// Hack to avoid Go complaining if time isn't used.
|
@ -1,11 +1,11 @@
|
|||||||
// goupnp is an implementation of a client for various UPnP services.
|
// goupnp is an implementation of a client for various UPnP services.
|
||||||
//
|
//
|
||||||
// For most uses, it is recommended to use the code-generated packages under
|
// For most uses, it is recommended to use the code-generated packages under
|
||||||
// github.com/fjl/goupnp/dcps. Example use is shown at
|
// github.com/huin/goupnp/dcps. Example use is shown at
|
||||||
// http://godoc.org/github.com/fjl/goupnp/example
|
// http://godoc.org/github.com/huin/goupnp/example
|
||||||
//
|
//
|
||||||
// A commonly used client is internetgateway1.WANPPPConnection1:
|
// A commonly used client is internetgateway1.WANPPPConnection1:
|
||||||
// http://godoc.org/github.com/fjl/goupnp/dcps/internetgateway1#WANPPPConnection1
|
// http://godoc.org/github.com/huin/goupnp/dcps/internetgateway1#WANPPPConnection1
|
||||||
//
|
//
|
||||||
// Currently only a couple of schemas have code generated for them from the
|
// Currently only a couple of schemas have code generated for them from the
|
||||||
// UPnP example XML specifications. Not all methods will work on these clients,
|
// UPnP example XML specifications. Not all methods will work on these clients,
|
||||||
@ -20,8 +20,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/fjl/goupnp/httpu"
|
"github.com/huin/goupnp/httpu"
|
||||||
"github.com/fjl/goupnp/ssdp"
|
"github.com/huin/goupnp/ssdp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContextError is an error that wraps an error with some context information.
|
// ContextError is an error that wraps an error with some context information.
|
@ -2,8 +2,7 @@ package goupnp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/huin/goupnp/soap"
|
||||||
"github.com/fjl/goupnp/soap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServiceClient is a SOAP client, root device and the service for the SOAP
|
// ServiceClient is a SOAP client, root device and the service for the SOAP
|
@ -10,7 +10,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fjl/goupnp/httpu"
|
"github.com/huin/goupnp/httpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fjl/goupnp/httpu"
|
"github.com/huin/goupnp/httpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
24
Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore
generated
vendored
24
Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
||||||
|
|
||||||
*~
|
|
28
Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE
generated
vendored
28
Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE
generated
vendored
@ -1,28 +0,0 @@
|
|||||||
Copyright (c) 2013 Kyle Isom <kyle@tyrfingr.is>
|
|
||||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
94
Godeps/_workspace/src/github.com/obscuren/ecies/README
generated
vendored
94
Godeps/_workspace/src/github.com/obscuren/ecies/README
generated
vendored
@ -1,94 +0,0 @@
|
|||||||
# NOTE
|
|
||||||
|
|
||||||
This implementation is direct fork of Kylom's implementation. I claim no authorship over this code apart from some minor modifications.
|
|
||||||
Please be aware this code **has not yet been reviewed**.
|
|
||||||
|
|
||||||
ecies implements the Elliptic Curve Integrated Encryption Scheme.
|
|
||||||
|
|
||||||
The package is designed to be compliant with the appropriate NIST
|
|
||||||
standards, and therefore doesn't support the full SEC 1 algorithm set.
|
|
||||||
|
|
||||||
|
|
||||||
STATUS:
|
|
||||||
|
|
||||||
ecies should be ready for use. The ASN.1 support is only complete so
|
|
||||||
far as to supported the listed algorithms before.
|
|
||||||
|
|
||||||
|
|
||||||
CAVEATS
|
|
||||||
|
|
||||||
1. CMAC support is currently not present.
|
|
||||||
|
|
||||||
|
|
||||||
SUPPORTED ALGORITHMS
|
|
||||||
|
|
||||||
SYMMETRIC CIPHERS HASH FUNCTIONS
|
|
||||||
AES128 SHA-1
|
|
||||||
AES192 SHA-224
|
|
||||||
AES256 SHA-256
|
|
||||||
SHA-384
|
|
||||||
ELLIPTIC CURVE SHA-512
|
|
||||||
P256
|
|
||||||
P384 KEY DERIVATION FUNCTION
|
|
||||||
P521 NIST SP 800-65a Concatenation KDF
|
|
||||||
|
|
||||||
Curve P224 isn't supported because it does not provide a minimum security
|
|
||||||
level of AES128 with HMAC-SHA1. According to NIST SP 800-57, the security
|
|
||||||
level of P224 is 112 bits of security. Symmetric ciphers use CTR-mode;
|
|
||||||
message tags are computed using HMAC-<HASH> function.
|
|
||||||
|
|
||||||
|
|
||||||
CURVE SELECTION
|
|
||||||
|
|
||||||
According to NIST SP 800-57, the following curves should be selected:
|
|
||||||
|
|
||||||
+----------------+-------+
|
|
||||||
| SYMMETRIC SIZE | CURVE |
|
|
||||||
+----------------+-------+
|
|
||||||
| 128-bit | P256 |
|
|
||||||
+----------------+-------+
|
|
||||||
| 192-bit | P384 |
|
|
||||||
+----------------+-------+
|
|
||||||
| 256-bit | P521 |
|
|
||||||
+----------------+-------+
|
|
||||||
|
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
1. Look at serialising the parameters with the SEC 1 ASN.1 module.
|
|
||||||
2. Validate ASN.1 formats with SEC 1.
|
|
||||||
|
|
||||||
|
|
||||||
TEST VECTORS
|
|
||||||
|
|
||||||
The only test vectors I've found so far date from 1993, predating AES
|
|
||||||
and including only 163-bit curves. Therefore, there are no published
|
|
||||||
test vectors to compare to.
|
|
||||||
|
|
||||||
|
|
||||||
LICENSE
|
|
||||||
|
|
||||||
ecies is released under the same license as the Go source code. See the
|
|
||||||
LICENSE file for details.
|
|
||||||
|
|
||||||
|
|
||||||
REFERENCES
|
|
||||||
|
|
||||||
* SEC (Standard for Efficient Cryptography) 1, version 2.0: Elliptic
|
|
||||||
Curve Cryptography; Certicom, May 2009.
|
|
||||||
http://www.secg.org/sec1-v2.pdf
|
|
||||||
* GEC (Guidelines for Efficient Cryptography) 2, version 0.3: Test
|
|
||||||
Vectors for SEC 1; Certicom, September 1999.
|
|
||||||
http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf
|
|
||||||
* NIST SP 800-56a: Recommendation for Pair-Wise Key Establishment Schemes
|
|
||||||
Using Discrete Logarithm Cryptography. National Institute of Standards
|
|
||||||
and Technology, May 2007.
|
|
||||||
http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf
|
|
||||||
* Suite B Implementer’s Guide to NIST SP 800-56A. National Security
|
|
||||||
Agency, July 28, 2009.
|
|
||||||
http://www.nsa.gov/ia/_files/SuiteB_Implementer_G-113808.pdf
|
|
||||||
* NIST SP 800-57: Recommendation for Key Management – Part 1: General
|
|
||||||
(Revision 3). National Institute of Standards and Technology, July
|
|
||||||
2012.
|
|
||||||
http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf
|
|
||||||
|
|
556
Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go
generated
vendored
556
Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go
generated
vendored
@ -1,556 +0,0 @@
|
|||||||
package ecies
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/sha512"
|
|
||||||
"encoding/asn1"
|
|
||||||
"encoding/pem"
|
|
||||||
"fmt"
|
|
||||||
"hash"
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
secgScheme = []int{1, 3, 132, 1}
|
|
||||||
shaScheme = []int{2, 16, 840, 1, 101, 3, 4, 2}
|
|
||||||
ansiX962Scheme = []int{1, 2, 840, 10045}
|
|
||||||
x963Scheme = []int{1, 2, 840, 63, 0}
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrInvalidPrivateKey = fmt.Errorf("ecies: invalid private key")
|
|
||||||
|
|
||||||
func doScheme(base, v []int) asn1.ObjectIdentifier {
|
|
||||||
var oidInts asn1.ObjectIdentifier
|
|
||||||
oidInts = append(oidInts, base...)
|
|
||||||
return append(oidInts, v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// curve OID code taken from crypto/x509, including
|
|
||||||
// - oidNameCurve*
|
|
||||||
// - namedCurveFromOID
|
|
||||||
// - oidFromNamedCurve
|
|
||||||
// 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
|
|
||||||
type secgNamedCurve asn1.ObjectIdentifier
|
|
||||||
|
|
||||||
var (
|
|
||||||
secgNamedCurveP224 = secgNamedCurve{1, 3, 132, 0, 33}
|
|
||||||
secgNamedCurveP256 = secgNamedCurve{1, 2, 840, 10045, 3, 1, 7}
|
|
||||||
secgNamedCurveP384 = secgNamedCurve{1, 3, 132, 0, 34}
|
|
||||||
secgNamedCurveP521 = secgNamedCurve{1, 3, 132, 0, 35}
|
|
||||||
rawCurveP224 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 3}
|
|
||||||
rawCurveP256 = []byte{6, 8, 4, 2, 1, 3, 4, 7, 2, 2, 0, 6, 6, 1, 3, 1, 7}
|
|
||||||
rawCurveP384 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 4}
|
|
||||||
rawCurveP521 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 5}
|
|
||||||
)
|
|
||||||
|
|
||||||
func rawCurve(curve elliptic.Curve) []byte {
|
|
||||||
switch curve {
|
|
||||||
case elliptic.P224():
|
|
||||||
return rawCurveP224
|
|
||||||
case elliptic.P256():
|
|
||||||
return rawCurveP256
|
|
||||||
case elliptic.P384():
|
|
||||||
return rawCurveP384
|
|
||||||
case elliptic.P521():
|
|
||||||
return rawCurveP521
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (curve secgNamedCurve) Equal(curve2 secgNamedCurve) bool {
|
|
||||||
if len(curve) != len(curve2) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, _ := range curve {
|
|
||||||
if curve[i] != curve2[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func namedCurveFromOID(curve secgNamedCurve) elliptic.Curve {
|
|
||||||
switch {
|
|
||||||
case curve.Equal(secgNamedCurveP224):
|
|
||||||
return elliptic.P224()
|
|
||||||
case curve.Equal(secgNamedCurveP256):
|
|
||||||
return elliptic.P256()
|
|
||||||
case curve.Equal(secgNamedCurveP384):
|
|
||||||
return elliptic.P384()
|
|
||||||
case curve.Equal(secgNamedCurveP521):
|
|
||||||
return elliptic.P521()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func oidFromNamedCurve(curve elliptic.Curve) (secgNamedCurve, bool) {
|
|
||||||
switch curve {
|
|
||||||
case elliptic.P224():
|
|
||||||
return secgNamedCurveP224, true
|
|
||||||
case elliptic.P256():
|
|
||||||
return secgNamedCurveP256, true
|
|
||||||
case elliptic.P384():
|
|
||||||
return secgNamedCurveP384, true
|
|
||||||
case elliptic.P521():
|
|
||||||
return secgNamedCurveP521, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// asnAlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
|
|
||||||
// 5280, section 4.1.1.2.
|
|
||||||
type asnAlgorithmIdentifier struct {
|
|
||||||
Algorithm asn1.ObjectIdentifier
|
|
||||||
Parameters asn1.RawValue `asn1:"optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a asnAlgorithmIdentifier) Cmp(b asnAlgorithmIdentifier) bool {
|
|
||||||
if len(a.Algorithm) != len(b.Algorithm) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, _ := range a.Algorithm {
|
|
||||||
if a.Algorithm[i] != b.Algorithm[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type asnHashFunction asnAlgorithmIdentifier
|
|
||||||
|
|
||||||
var (
|
|
||||||
oidSHA1 = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26}
|
|
||||||
oidSHA224 = doScheme(shaScheme, []int{4})
|
|
||||||
oidSHA256 = doScheme(shaScheme, []int{1})
|
|
||||||
oidSHA384 = doScheme(shaScheme, []int{2})
|
|
||||||
oidSHA512 = doScheme(shaScheme, []int{3})
|
|
||||||
)
|
|
||||||
|
|
||||||
func hashFromOID(oid asn1.ObjectIdentifier) func() hash.Hash {
|
|
||||||
switch {
|
|
||||||
case oid.Equal(oidSHA1):
|
|
||||||
return sha1.New
|
|
||||||
case oid.Equal(oidSHA224):
|
|
||||||
return sha256.New224
|
|
||||||
case oid.Equal(oidSHA256):
|
|
||||||
return sha256.New
|
|
||||||
case oid.Equal(oidSHA384):
|
|
||||||
return sha512.New384
|
|
||||||
case oid.Equal(oidSHA512):
|
|
||||||
return sha512.New
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func oidFromHash(hash crypto.Hash) (asn1.ObjectIdentifier, bool) {
|
|
||||||
switch hash {
|
|
||||||
case crypto.SHA1:
|
|
||||||
return oidSHA1, true
|
|
||||||
case crypto.SHA224:
|
|
||||||
return oidSHA224, true
|
|
||||||
case crypto.SHA256:
|
|
||||||
return oidSHA256, true
|
|
||||||
case crypto.SHA384:
|
|
||||||
return oidSHA384, true
|
|
||||||
case crypto.SHA512:
|
|
||||||
return oidSHA512, true
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
asnAlgoSHA1 = asnHashFunction{
|
|
||||||
Algorithm: oidSHA1,
|
|
||||||
}
|
|
||||||
asnAlgoSHA224 = asnHashFunction{
|
|
||||||
Algorithm: oidSHA224,
|
|
||||||
}
|
|
||||||
asnAlgoSHA256 = asnHashFunction{
|
|
||||||
Algorithm: oidSHA256,
|
|
||||||
}
|
|
||||||
asnAlgoSHA384 = asnHashFunction{
|
|
||||||
Algorithm: oidSHA384,
|
|
||||||
}
|
|
||||||
asnAlgoSHA512 = asnHashFunction{
|
|
||||||
Algorithm: oidSHA512,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// type ASNasnSubjectPublicKeyInfo struct {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
|
||||||
type asnSubjectPublicKeyInfo struct {
|
|
||||||
Algorithm asn1.ObjectIdentifier
|
|
||||||
PublicKey asn1.BitString
|
|
||||||
Supplements ecpksSupplements `asn1:"optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type asnECPKAlgorithms struct {
|
|
||||||
Type asn1.ObjectIdentifier
|
|
||||||
}
|
|
||||||
|
|
||||||
var idPublicKeyType = doScheme(ansiX962Scheme, []int{2})
|
|
||||||
var idEcPublicKey = doScheme(idPublicKeyType, []int{1})
|
|
||||||
var idEcPublicKeySupplemented = doScheme(idPublicKeyType, []int{0})
|
|
||||||
|
|
||||||
func curveToRaw(curve elliptic.Curve) (rv asn1.RawValue, ok bool) {
|
|
||||||
switch curve {
|
|
||||||
case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521():
|
|
||||||
raw := rawCurve(curve)
|
|
||||||
return asn1.RawValue{
|
|
||||||
Tag: 30,
|
|
||||||
Bytes: raw[2:],
|
|
||||||
FullBytes: raw,
|
|
||||||
}, true
|
|
||||||
default:
|
|
||||||
return rv, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func asnECPublicKeyType(curve elliptic.Curve) (algo asnAlgorithmIdentifier, ok bool) {
|
|
||||||
raw, ok := curveToRaw(curve)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
return asnAlgorithmIdentifier{Algorithm: idEcPublicKey,
|
|
||||||
Parameters: raw}, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type asnECPrivKeyVer int
|
|
||||||
|
|
||||||
var asnECPrivKeyVer1 asnECPrivKeyVer = 1
|
|
||||||
|
|
||||||
type asnPrivateKey struct {
|
|
||||||
Version asnECPrivKeyVer
|
|
||||||
Private []byte
|
|
||||||
Curve secgNamedCurve `asn1:"optional"`
|
|
||||||
Public asn1.BitString
|
|
||||||
}
|
|
||||||
|
|
||||||
var asnECDH = doScheme(secgScheme, []int{12})
|
|
||||||
|
|
||||||
type asnECDHAlgorithm asnAlgorithmIdentifier
|
|
||||||
|
|
||||||
var (
|
|
||||||
dhSinglePass_stdDH_sha1kdf = asnECDHAlgorithm{
|
|
||||||
Algorithm: doScheme(x963Scheme, []int{2}),
|
|
||||||
}
|
|
||||||
dhSinglePass_stdDH_sha256kdf = asnECDHAlgorithm{
|
|
||||||
Algorithm: doScheme(secgScheme, []int{11, 1}),
|
|
||||||
}
|
|
||||||
dhSinglePass_stdDH_sha384kdf = asnECDHAlgorithm{
|
|
||||||
Algorithm: doScheme(secgScheme, []int{11, 2}),
|
|
||||||
}
|
|
||||||
dhSinglePass_stdDH_sha224kdf = asnECDHAlgorithm{
|
|
||||||
Algorithm: doScheme(secgScheme, []int{11, 0}),
|
|
||||||
}
|
|
||||||
dhSinglePass_stdDH_sha512kdf = asnECDHAlgorithm{
|
|
||||||
Algorithm: doScheme(secgScheme, []int{11, 3}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (a asnECDHAlgorithm) Cmp(b asnECDHAlgorithm) bool {
|
|
||||||
if len(a.Algorithm) != len(b.Algorithm) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, _ := range a.Algorithm {
|
|
||||||
if a.Algorithm[i] != b.Algorithm[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// asnNISTConcatenation is the only supported KDF at this time.
|
|
||||||
type asnKeyDerivationFunction asnAlgorithmIdentifier
|
|
||||||
|
|
||||||
var asnNISTConcatenationKDF = asnKeyDerivationFunction{
|
|
||||||
Algorithm: doScheme(secgScheme, []int{17, 1}),
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a asnKeyDerivationFunction) Cmp(b asnKeyDerivationFunction) bool {
|
|
||||||
if len(a.Algorithm) != len(b.Algorithm) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, _ := range a.Algorithm {
|
|
||||||
if a.Algorithm[i] != b.Algorithm[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var eciesRecommendedParameters = doScheme(secgScheme, []int{7})
|
|
||||||
var eciesSpecifiedParameters = doScheme(secgScheme, []int{8})
|
|
||||||
|
|
||||||
type asnECIESParameters struct {
|
|
||||||
KDF asnKeyDerivationFunction `asn1:"optional"`
|
|
||||||
Sym asnSymmetricEncryption `asn1:"optional"`
|
|
||||||
MAC asnMessageAuthenticationCode `asn1:"optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type asnSymmetricEncryption asnAlgorithmIdentifier
|
|
||||||
|
|
||||||
var (
|
|
||||||
aes128CTRinECIES = asnSymmetricEncryption{
|
|
||||||
Algorithm: doScheme(secgScheme, []int{21, 0}),
|
|
||||||
}
|
|
||||||
aes192CTRinECIES = asnSymmetricEncryption{
|
|
||||||
Algorithm: doScheme(secgScheme, []int{21, 1}),
|
|
||||||
}
|
|
||||||
aes256CTRinECIES = asnSymmetricEncryption{
|
|
||||||
Algorithm: doScheme(secgScheme, []int{21, 2}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (a asnSymmetricEncryption) Cmp(b asnSymmetricEncryption) bool {
|
|
||||||
if len(a.Algorithm) != len(b.Algorithm) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, _ := range a.Algorithm {
|
|
||||||
if a.Algorithm[i] != b.Algorithm[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type asnMessageAuthenticationCode asnAlgorithmIdentifier
|
|
||||||
|
|
||||||
var (
|
|
||||||
hmacFull = asnMessageAuthenticationCode{
|
|
||||||
Algorithm: doScheme(secgScheme, []int{22}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (a asnMessageAuthenticationCode) Cmp(b asnMessageAuthenticationCode) bool {
|
|
||||||
if len(a.Algorithm) != len(b.Algorithm) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, _ := range a.Algorithm {
|
|
||||||
if a.Algorithm[i] != b.Algorithm[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type ecpksSupplements struct {
|
|
||||||
ECDomain secgNamedCurve
|
|
||||||
ECCAlgorithms eccAlgorithmSet
|
|
||||||
}
|
|
||||||
|
|
||||||
type eccAlgorithmSet struct {
|
|
||||||
ECDH asnECDHAlgorithm `asn1:"optional"`
|
|
||||||
ECIES asnECIESParameters `asn1:"optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalSubjectPublicKeyInfo(pub *PublicKey) (subj asnSubjectPublicKeyInfo, err error) {
|
|
||||||
subj.Algorithm = idEcPublicKeySupplemented
|
|
||||||
curve, ok := oidFromNamedCurve(pub.Curve)
|
|
||||||
if !ok {
|
|
||||||
err = ErrInvalidPublicKey
|
|
||||||
return
|
|
||||||
}
|
|
||||||
subj.Supplements.ECDomain = curve
|
|
||||||
if pub.Params != nil {
|
|
||||||
subj.Supplements.ECCAlgorithms.ECDH = paramsToASNECDH(pub.Params)
|
|
||||||
subj.Supplements.ECCAlgorithms.ECIES = paramsToASNECIES(pub.Params)
|
|
||||||
}
|
|
||||||
pubkey := elliptic.Marshal(pub.Curve, pub.X, pub.Y)
|
|
||||||
subj.PublicKey = asn1.BitString{
|
|
||||||
BitLength: len(pubkey) * 8,
|
|
||||||
Bytes: pubkey,
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode a public key to DER format.
|
|
||||||
func MarshalPublic(pub *PublicKey) ([]byte, error) {
|
|
||||||
subj, err := marshalSubjectPublicKeyInfo(pub)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return asn1.Marshal(subj)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a DER-encoded public key.
|
|
||||||
func UnmarshalPublic(in []byte) (pub *PublicKey, err error) {
|
|
||||||
var subj asnSubjectPublicKeyInfo
|
|
||||||
|
|
||||||
if _, err = asn1.Unmarshal(in, &subj); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !subj.Algorithm.Equal(idEcPublicKeySupplemented) {
|
|
||||||
err = ErrInvalidPublicKey
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pub = new(PublicKey)
|
|
||||||
pub.Curve = namedCurveFromOID(subj.Supplements.ECDomain)
|
|
||||||
x, y := elliptic.Unmarshal(pub.Curve, subj.PublicKey.Bytes)
|
|
||||||
if x == nil {
|
|
||||||
err = ErrInvalidPublicKey
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pub.X = x
|
|
||||||
pub.Y = y
|
|
||||||
pub.Params = new(ECIESParams)
|
|
||||||
asnECIEStoParams(subj.Supplements.ECCAlgorithms.ECIES, pub.Params)
|
|
||||||
asnECDHtoParams(subj.Supplements.ECCAlgorithms.ECDH, pub.Params)
|
|
||||||
if pub.Params == nil {
|
|
||||||
if pub.Params = ParamsFromCurve(pub.Curve); pub.Params == nil {
|
|
||||||
err = ErrInvalidPublicKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalPrivateKey(prv *PrivateKey) (ecprv asnPrivateKey, err error) {
|
|
||||||
ecprv.Version = asnECPrivKeyVer1
|
|
||||||
ecprv.Private = prv.D.Bytes()
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
ecprv.Curve, ok = oidFromNamedCurve(prv.PublicKey.Curve)
|
|
||||||
if !ok {
|
|
||||||
err = ErrInvalidPrivateKey
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var pub []byte
|
|
||||||
if pub, err = MarshalPublic(&prv.PublicKey); err != nil {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
ecprv.Public = asn1.BitString{
|
|
||||||
BitLength: len(pub) * 8,
|
|
||||||
Bytes: pub,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode a private key to DER format.
|
|
||||||
func MarshalPrivate(prv *PrivateKey) ([]byte, error) {
|
|
||||||
ecprv, err := marshalPrivateKey(prv)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return asn1.Marshal(ecprv)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a private key from a DER-encoded format.
|
|
||||||
func UnmarshalPrivate(in []byte) (prv *PrivateKey, err error) {
|
|
||||||
var ecprv asnPrivateKey
|
|
||||||
|
|
||||||
if _, err = asn1.Unmarshal(in, &ecprv); err != nil {
|
|
||||||
return
|
|
||||||
} else if ecprv.Version != asnECPrivKeyVer1 {
|
|
||||||
err = ErrInvalidPrivateKey
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
privateCurve := namedCurveFromOID(ecprv.Curve)
|
|
||||||
if privateCurve == nil {
|
|
||||||
err = ErrInvalidPrivateKey
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
prv = new(PrivateKey)
|
|
||||||
prv.D = new(big.Int).SetBytes(ecprv.Private)
|
|
||||||
|
|
||||||
if pub, err := UnmarshalPublic(ecprv.Public.Bytes); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else {
|
|
||||||
prv.PublicKey = *pub
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export a public key to PEM format.
|
|
||||||
func ExportPublicPEM(pub *PublicKey) (out []byte, err error) {
|
|
||||||
der, err := MarshalPublic(pub)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var block pem.Block
|
|
||||||
block.Type = "ELLIPTIC CURVE PUBLIC KEY"
|
|
||||||
block.Bytes = der
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
err = pem.Encode(buf, &block)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
out = buf.Bytes()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export a private key to PEM format.
|
|
||||||
func ExportPrivatePEM(prv *PrivateKey) (out []byte, err error) {
|
|
||||||
der, err := MarshalPrivate(prv)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var block pem.Block
|
|
||||||
block.Type = "ELLIPTIC CURVE PRIVATE KEY"
|
|
||||||
block.Bytes = der
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
err = pem.Encode(buf, &block)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
out = buf.Bytes()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import a PEM-encoded public key.
|
|
||||||
func ImportPublicPEM(in []byte) (pub *PublicKey, err error) {
|
|
||||||
p, _ := pem.Decode(in)
|
|
||||||
if p == nil || p.Type != "ELLIPTIC CURVE PUBLIC KEY" {
|
|
||||||
return nil, ErrInvalidPublicKey
|
|
||||||
}
|
|
||||||
|
|
||||||
pub, err = UnmarshalPublic(p.Bytes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import a PEM-encoded private key.
|
|
||||||
func ImportPrivatePEM(in []byte) (prv *PrivateKey, err error) {
|
|
||||||
p, _ := pem.Decode(in)
|
|
||||||
if p == nil || p.Type != "ELLIPTIC CURVE PRIVATE KEY" {
|
|
||||||
return nil, ErrInvalidPrivateKey
|
|
||||||
}
|
|
||||||
|
|
||||||
prv, err = UnmarshalPrivate(p.Bytes)
|
|
||||||
return
|
|
||||||
}
|
|
326
Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go
generated
vendored
326
Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go
generated
vendored
@ -1,326 +0,0 @@
|
|||||||
package ecies
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/subtle"
|
|
||||||
"fmt"
|
|
||||||
"hash"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrImport = fmt.Errorf("ecies: failed to import key")
|
|
||||||
ErrInvalidCurve = fmt.Errorf("ecies: invalid elliptic curve")
|
|
||||||
ErrInvalidParams = fmt.Errorf("ecies: invalid ECIES parameters")
|
|
||||||
ErrInvalidPublicKey = fmt.Errorf("ecies: invalid public key")
|
|
||||||
ErrSharedKeyTooBig = fmt.Errorf("ecies: shared key is too big")
|
|
||||||
)
|
|
||||||
|
|
||||||
// PublicKey is a representation of an elliptic curve public key.
|
|
||||||
type PublicKey struct {
|
|
||||||
X *big.Int
|
|
||||||
Y *big.Int
|
|
||||||
elliptic.Curve
|
|
||||||
Params *ECIESParams
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export an ECIES public key as an ECDSA public key.
|
|
||||||
func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey {
|
|
||||||
return &ecdsa.PublicKey{pub.Curve, pub.X, pub.Y}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import an ECDSA public key as an ECIES public key.
|
|
||||||
func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey {
|
|
||||||
return &PublicKey{
|
|
||||||
X: pub.X,
|
|
||||||
Y: pub.Y,
|
|
||||||
Curve: pub.Curve,
|
|
||||||
Params: ParamsFromCurve(pub.Curve),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrivateKey is a representation of an elliptic curve private key.
|
|
||||||
type PrivateKey struct {
|
|
||||||
PublicKey
|
|
||||||
D *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export an ECIES private key as an ECDSA private key.
|
|
||||||
func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey {
|
|
||||||
pub := &prv.PublicKey
|
|
||||||
pubECDSA := pub.ExportECDSA()
|
|
||||||
return &ecdsa.PrivateKey{*pubECDSA, prv.D}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import an ECDSA private key as an ECIES private key.
|
|
||||||
func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
|
|
||||||
pub := ImportECDSAPublic(&prv.PublicKey)
|
|
||||||
return &PrivateKey{*pub, prv.D}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate an elliptic curve public / private keypair. If params is nil,
|
|
||||||
// the recommended default paramters for the key will be chosen.
|
|
||||||
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
|
|
||||||
pb, x, y, err := elliptic.GenerateKey(curve, rand)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
prv = new(PrivateKey)
|
|
||||||
prv.PublicKey.X = x
|
|
||||||
prv.PublicKey.Y = y
|
|
||||||
prv.PublicKey.Curve = curve
|
|
||||||
prv.D = new(big.Int).SetBytes(pb)
|
|
||||||
if params == nil {
|
|
||||||
params = ParamsFromCurve(curve)
|
|
||||||
}
|
|
||||||
prv.PublicKey.Params = params
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// MaxSharedKeyLength returns the maximum length of the shared key the
|
|
||||||
// public key can produce.
|
|
||||||
func MaxSharedKeyLength(pub *PublicKey) int {
|
|
||||||
return (pub.Curve.Params().BitSize + 7) / 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// ECDH key agreement method used to establish secret keys for encryption.
|
|
||||||
func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) {
|
|
||||||
if prv.PublicKey.Curve != pub.Curve {
|
|
||||||
err = ErrInvalidCurve
|
|
||||||
return
|
|
||||||
}
|
|
||||||
x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes())
|
|
||||||
if x == nil || (x.BitLen()+7)/8 < (skLen+macLen) {
|
|
||||||
err = ErrSharedKeyTooBig
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sk = x.Bytes()[:skLen+macLen]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrKeyDataTooLong = fmt.Errorf("ecies: can't supply requested key data")
|
|
||||||
ErrSharedTooLong = fmt.Errorf("ecies: shared secret is too long")
|
|
||||||
ErrInvalidMessage = fmt.Errorf("ecies: invalid message")
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
big2To32 = new(big.Int).Exp(big.NewInt(2), big.NewInt(32), nil)
|
|
||||||
big2To32M1 = new(big.Int).Sub(big2To32, big.NewInt(1))
|
|
||||||
)
|
|
||||||
|
|
||||||
func incCounter(ctr []byte) {
|
|
||||||
if ctr[3]++; ctr[3] != 0 {
|
|
||||||
return
|
|
||||||
} else if ctr[2]++; ctr[2] != 0 {
|
|
||||||
return
|
|
||||||
} else if ctr[1]++; ctr[1] != 0 {
|
|
||||||
return
|
|
||||||
} else if ctr[0]++; ctr[0] != 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1).
|
|
||||||
func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) {
|
|
||||||
if s1 == nil {
|
|
||||||
s1 = make([]byte, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
reps := ((kdLen + 7) * 8) / (hash.BlockSize() * 8)
|
|
||||||
if big.NewInt(int64(reps)).Cmp(big2To32M1) > 0 {
|
|
||||||
fmt.Println(big2To32M1)
|
|
||||||
return nil, ErrKeyDataTooLong
|
|
||||||
}
|
|
||||||
|
|
||||||
counter := []byte{0, 0, 0, 1}
|
|
||||||
k = make([]byte, 0)
|
|
||||||
|
|
||||||
for i := 0; i <= reps; i++ {
|
|
||||||
hash.Write(counter)
|
|
||||||
hash.Write(z)
|
|
||||||
hash.Write(s1)
|
|
||||||
k = append(k, hash.Sum(nil)...)
|
|
||||||
hash.Reset()
|
|
||||||
incCounter(counter)
|
|
||||||
}
|
|
||||||
|
|
||||||
k = k[:kdLen]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// messageTag computes the MAC of a message (called the tag) as per
|
|
||||||
// SEC 1, 3.5.
|
|
||||||
func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
|
|
||||||
if shared == nil {
|
|
||||||
shared = make([]byte, 0)
|
|
||||||
}
|
|
||||||
mac := hmac.New(hash, km)
|
|
||||||
mac.Write(msg)
|
|
||||||
tag := mac.Sum(nil)
|
|
||||||
return tag
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate an initialisation vector for CTR mode.
|
|
||||||
func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) {
|
|
||||||
iv = make([]byte, params.BlockSize)
|
|
||||||
_, err = io.ReadFull(rand, iv)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// symEncrypt carries out CTR encryption using the block cipher specified in the
|
|
||||||
// parameters.
|
|
||||||
func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) {
|
|
||||||
c, err := params.Cipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
iv, err := generateIV(params, rand)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctr := cipher.NewCTR(c, iv)
|
|
||||||
|
|
||||||
ct = make([]byte, len(m)+params.BlockSize)
|
|
||||||
copy(ct, iv)
|
|
||||||
ctr.XORKeyStream(ct[params.BlockSize:], m)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// symDecrypt carries out CTR decryption using the block cipher specified in
|
|
||||||
// the parameters
|
|
||||||
func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte, err error) {
|
|
||||||
c, err := params.Cipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctr := cipher.NewCTR(c, ct[:params.BlockSize])
|
|
||||||
|
|
||||||
m = make([]byte, len(ct)-params.BlockSize)
|
|
||||||
ctr.XORKeyStream(m, ct[params.BlockSize:])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. If
|
|
||||||
// the shared information parameters aren't being used, they should be
|
|
||||||
// nil.
|
|
||||||
func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) {
|
|
||||||
params := pub.Params
|
|
||||||
if params == nil {
|
|
||||||
if params = ParamsFromCurve(pub.Curve); params == nil {
|
|
||||||
err = ErrUnsupportedECIESParameters
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
R, err := GenerateKey(rand, pub.Curve, params)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hash := params.Hash()
|
|
||||||
z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
Ke := K[:params.KeyLen]
|
|
||||||
Km := K[params.KeyLen:]
|
|
||||||
hash.Write(Km)
|
|
||||||
Km = hash.Sum(nil)
|
|
||||||
hash.Reset()
|
|
||||||
|
|
||||||
em, err := symEncrypt(rand, params, Ke, m)
|
|
||||||
if err != nil || len(em) <= params.BlockSize {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
d := messageTag(params.Hash, Km, em, s2)
|
|
||||||
|
|
||||||
Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y)
|
|
||||||
ct = make([]byte, len(Rb)+len(em)+len(d))
|
|
||||||
copy(ct, Rb)
|
|
||||||
copy(ct[len(Rb):], em)
|
|
||||||
copy(ct[len(Rb)+len(em):], d)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt decrypts an ECIES ciphertext.
|
|
||||||
func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err error) {
|
|
||||||
if c == nil || len(c) == 0 {
|
|
||||||
err = ErrInvalidMessage
|
|
||||||
return
|
|
||||||
}
|
|
||||||
params := prv.PublicKey.Params
|
|
||||||
if params == nil {
|
|
||||||
if params = ParamsFromCurve(prv.PublicKey.Curve); params == nil {
|
|
||||||
err = ErrUnsupportedECIESParameters
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hash := params.Hash()
|
|
||||||
|
|
||||||
var (
|
|
||||||
rLen int
|
|
||||||
hLen int = hash.Size()
|
|
||||||
mStart int
|
|
||||||
mEnd int
|
|
||||||
)
|
|
||||||
|
|
||||||
switch c[0] {
|
|
||||||
case 2, 3, 4:
|
|
||||||
rLen = ((prv.PublicKey.Curve.Params().BitSize + 7) / 4)
|
|
||||||
if len(c) < (rLen + hLen + 1) {
|
|
||||||
err = ErrInvalidMessage
|
|
||||||
return
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
err = ErrInvalidPublicKey
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mStart = rLen
|
|
||||||
mEnd = len(c) - hLen
|
|
||||||
|
|
||||||
R := new(PublicKey)
|
|
||||||
R.Curve = prv.PublicKey.Curve
|
|
||||||
R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen])
|
|
||||||
if R.X == nil {
|
|
||||||
err = ErrInvalidPublicKey
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Ke := K[:params.KeyLen]
|
|
||||||
Km := K[params.KeyLen:]
|
|
||||||
hash.Write(Km)
|
|
||||||
Km = hash.Sum(nil)
|
|
||||||
hash.Reset()
|
|
||||||
|
|
||||||
d := messageTag(params.Hash, Km, c[mStart:mEnd], s2)
|
|
||||||
if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 {
|
|
||||||
err = ErrInvalidMessage
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m, err = symDecrypt(rand, params, Ke, c[mStart:mEnd])
|
|
||||||
return
|
|
||||||
}
|
|
489
Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go
generated
vendored
489
Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go
generated
vendored
@ -1,489 +0,0 @@
|
|||||||
package ecies
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/sha256"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var dumpEnc bool
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
flDump := flag.Bool("dump", false, "write encrypted test message to file")
|
|
||||||
flag.Parse()
|
|
||||||
dumpEnc = *flDump
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the KDF generates appropriately sized keys.
|
|
||||||
func TestKDF(t *testing.T) {
|
|
||||||
msg := []byte("Hello, world")
|
|
||||||
h := sha256.New()
|
|
||||||
|
|
||||||
k, err := concatKDF(h, msg, nil, 64)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if len(k) != 64 {
|
|
||||||
fmt.Printf("KDF: generated key is the wrong size (%d instead of 64\n",
|
|
||||||
len(k))
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var skLen int
|
|
||||||
var ErrBadSharedKeys = fmt.Errorf("ecies: shared keys don't match")
|
|
||||||
|
|
||||||
// cmpParams compares a set of ECIES parameters. We assume, as per the
|
|
||||||
// docs, that AES is the only supported symmetric encryption algorithm.
|
|
||||||
func cmpParams(p1, p2 *ECIESParams) bool {
|
|
||||||
if p1.hashAlgo != p2.hashAlgo {
|
|
||||||
return false
|
|
||||||
} else if p1.KeyLen != p2.KeyLen {
|
|
||||||
return false
|
|
||||||
} else if p1.BlockSize != p2.BlockSize {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// cmpPublic returns true if the two public keys represent the same pojnt.
|
|
||||||
func cmpPublic(pub1, pub2 PublicKey) bool {
|
|
||||||
if pub1.X == nil || pub1.Y == nil {
|
|
||||||
fmt.Println(ErrInvalidPublicKey.Error())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if pub2.X == nil || pub2.Y == nil {
|
|
||||||
fmt.Println(ErrInvalidPublicKey.Error())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
pub1Out := elliptic.Marshal(pub1.Curve, pub1.X, pub1.Y)
|
|
||||||
pub2Out := elliptic.Marshal(pub2.Curve, pub2.X, pub2.Y)
|
|
||||||
|
|
||||||
return bytes.Equal(pub1Out, pub2Out)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cmpPrivate returns true if the two private keys are the same.
|
|
||||||
func cmpPrivate(prv1, prv2 *PrivateKey) bool {
|
|
||||||
if prv1 == nil || prv1.D == nil {
|
|
||||||
return false
|
|
||||||
} else if prv2 == nil || prv2.D == nil {
|
|
||||||
return false
|
|
||||||
} else if prv1.D.Cmp(prv2.D) != 0 {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return cmpPublic(prv1.PublicKey, prv2.PublicKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the ECDH component.
|
|
||||||
func TestSharedKey(t *testing.T) {
|
|
||||||
prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
skLen = MaxSharedKeyLength(&prv1.PublicKey) / 2
|
|
||||||
|
|
||||||
prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(sk1, sk2) {
|
|
||||||
fmt.Println(ErrBadSharedKeys.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the key generation code fails when too much key data is
|
|
||||||
// requested.
|
|
||||||
func TestTooBigSharedKey(t *testing.T) {
|
|
||||||
prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = prv1.GenerateShared(&prv2.PublicKey, skLen*2, skLen*2)
|
|
||||||
if err != ErrSharedKeyTooBig {
|
|
||||||
fmt.Println("ecdh: shared key should be too large for curve")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = prv2.GenerateShared(&prv1.PublicKey, skLen*2, skLen*2)
|
|
||||||
if err != ErrSharedKeyTooBig {
|
|
||||||
fmt.Println("ecdh: shared key should be too large for curve")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure a public key can be successfully marshalled and unmarshalled, and
|
|
||||||
// that the decoded key is the same as the original.
|
|
||||||
func TestMarshalPublic(t *testing.T) {
|
|
||||||
prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := MarshalPublic(&prv.PublicKey)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub, err := UnmarshalPublic(out)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !cmpPublic(prv.PublicKey, *pub) {
|
|
||||||
fmt.Println("ecies: failed to unmarshal public key")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that a private key can be encoded into DER format, and that
|
|
||||||
// the resulting key is properly parsed back into a public key.
|
|
||||||
func TestMarshalPrivate(t *testing.T) {
|
|
||||||
prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := MarshalPrivate(prv)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if dumpEnc {
|
|
||||||
ioutil.WriteFile("test.out", out, 0644)
|
|
||||||
}
|
|
||||||
|
|
||||||
prv2, err := UnmarshalPrivate(out)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !cmpPrivate(prv, prv2) {
|
|
||||||
fmt.Println("ecdh: private key import failed")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that a private key can be successfully encoded to PEM format, and
|
|
||||||
// the resulting key is properly parsed back in.
|
|
||||||
func TestPrivatePEM(t *testing.T) {
|
|
||||||
prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := ExportPrivatePEM(prv)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if dumpEnc {
|
|
||||||
ioutil.WriteFile("test.key", out, 0644)
|
|
||||||
}
|
|
||||||
|
|
||||||
prv2, err := ImportPrivatePEM(out)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
} else if !cmpPrivate(prv, prv2) {
|
|
||||||
fmt.Println("ecdh: import from PEM failed")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that a public key can be successfully encoded to PEM format, and
|
|
||||||
// the resulting key is properly parsed back in.
|
|
||||||
func TestPublicPEM(t *testing.T) {
|
|
||||||
prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := ExportPublicPEM(&prv.PublicKey)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if dumpEnc {
|
|
||||||
ioutil.WriteFile("test.pem", out, 0644)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub2, err := ImportPublicPEM(out)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
} else if !cmpPublic(prv.PublicKey, *pub2) {
|
|
||||||
fmt.Println("ecdh: import from PEM failed")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Benchmark the generation of P256 keys.
|
|
||||||
func BenchmarkGenerateKeyP256(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if _, err := GenerateKey(rand.Reader, elliptic.P256(), nil); err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
b.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Benchmark the generation of P256 shared keys.
|
|
||||||
func BenchmarkGenSharedKeyP256(b *testing.B) {
|
|
||||||
prv, err := GenerateKey(rand.Reader, elliptic.P256(), nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
b.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err := prv.GenerateShared(&prv.PublicKey, skLen, skLen)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
b.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that an encrypted message can be successfully decrypted.
|
|
||||||
func TestEncryptDecrypt(t *testing.T) {
|
|
||||||
prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Hello, world.")
|
|
||||||
ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(pt, message) {
|
|
||||||
fmt.Println("ecies: plaintext doesn't match message")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = prv1.Decrypt(rand.Reader, ct, nil, nil)
|
|
||||||
if err == nil {
|
|
||||||
fmt.Println("ecies: encryption should not have succeeded")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestMarshalEncryption validates the encode/decode produces a valid
|
|
||||||
// ECIES encryption key.
|
|
||||||
func TestMarshalEncryption(t *testing.T) {
|
|
||||||
prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := MarshalPrivate(prv1)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
prv2, err := UnmarshalPrivate(out)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Hello, world.")
|
|
||||||
ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(pt, message) {
|
|
||||||
fmt.Println("ecies: plaintext doesn't match message")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = prv1.Decrypt(rand.Reader, ct, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type testCase struct {
|
|
||||||
Curve elliptic.Curve
|
|
||||||
Name string
|
|
||||||
Expected bool
|
|
||||||
}
|
|
||||||
|
|
||||||
var testCases = []testCase{
|
|
||||||
testCase{
|
|
||||||
Curve: elliptic.P224(),
|
|
||||||
Name: "P224",
|
|
||||||
Expected: false,
|
|
||||||
},
|
|
||||||
testCase{
|
|
||||||
Curve: elliptic.P256(),
|
|
||||||
Name: "P256",
|
|
||||||
Expected: true,
|
|
||||||
},
|
|
||||||
testCase{
|
|
||||||
Curve: elliptic.P384(),
|
|
||||||
Name: "P384",
|
|
||||||
Expected: true,
|
|
||||||
},
|
|
||||||
testCase{
|
|
||||||
Curve: elliptic.P521(),
|
|
||||||
Name: "P521",
|
|
||||||
Expected: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test parameter selection for each curve, and that P224 fails automatic
|
|
||||||
// parameter selection (see README for a discussion of P224). Ensures that
|
|
||||||
// selecting a set of parameters automatically for the given curve works.
|
|
||||||
func TestParamSelection(t *testing.T) {
|
|
||||||
for _, c := range testCases {
|
|
||||||
testParamSelection(t, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testParamSelection(t *testing.T, c testCase) {
|
|
||||||
params := ParamsFromCurve(c.Curve)
|
|
||||||
if params == nil && c.Expected {
|
|
||||||
fmt.Printf("%s (%s)\n", ErrInvalidParams.Error(), c.Name)
|
|
||||||
t.FailNow()
|
|
||||||
} else if params != nil && !c.Expected {
|
|
||||||
fmt.Printf("ecies: parameters should be invalid (%s)\n",
|
|
||||||
c.Name)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s (%s)\n", err.Error(), c.Name)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s (%s)\n", err.Error(), c.Name)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Hello, world.")
|
|
||||||
ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s (%s)\n", err.Error(), c.Name)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s (%s)\n", err.Error(), c.Name)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(pt, message) {
|
|
||||||
fmt.Printf("ecies: plaintext doesn't match message (%s)\n",
|
|
||||||
c.Name)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = prv1.Decrypt(rand.Reader, ct, nil, nil)
|
|
||||||
if err == nil {
|
|
||||||
fmt.Printf("ecies: encryption should not have succeeded (%s)\n",
|
|
||||||
c.Name)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that the basic public key validation in the decryption operation
|
|
||||||
// works.
|
|
||||||
func TestBasicKeyValidation(t *testing.T) {
|
|
||||||
badBytes := []byte{0, 1, 5, 6, 7, 8, 9}
|
|
||||||
|
|
||||||
prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Hello, world.")
|
|
||||||
ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, b := range badBytes {
|
|
||||||
ct[0] = b
|
|
||||||
_, err := prv.Decrypt(rand.Reader, ct, nil, nil)
|
|
||||||
if err != ErrInvalidPublicKey {
|
|
||||||
fmt.Println("ecies: validated an invalid key")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
187
Godeps/_workspace/src/github.com/obscuren/ecies/params.go
generated
vendored
187
Godeps/_workspace/src/github.com/obscuren/ecies/params.go
generated
vendored
@ -1,187 +0,0 @@
|
|||||||
package ecies
|
|
||||||
|
|
||||||
// This file contains parameters for ECIES encryption, specifying the
|
|
||||||
// symmetric encryption and HMAC parameters.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/sha512"
|
|
||||||
"fmt"
|
|
||||||
"hash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// The default curve for this package is the NIST P256 curve, which
|
|
||||||
// provides security equivalent to AES-128.
|
|
||||||
var DefaultCurve = elliptic.P256()
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrUnsupportedECDHAlgorithm = fmt.Errorf("ecies: unsupported ECDH algorithm")
|
|
||||||
ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters")
|
|
||||||
)
|
|
||||||
|
|
||||||
type ECIESParams struct {
|
|
||||||
Hash func() hash.Hash // hash function
|
|
||||||
hashAlgo crypto.Hash
|
|
||||||
Cipher func([]byte) (cipher.Block, error) // symmetric cipher
|
|
||||||
BlockSize int // block size of symmetric cipher
|
|
||||||
KeyLen int // length of symmetric key
|
|
||||||
}
|
|
||||||
|
|
||||||
// Standard ECIES parameters:
|
|
||||||
// * ECIES using AES128 and HMAC-SHA-256-16
|
|
||||||
// * ECIES using AES256 and HMAC-SHA-256-32
|
|
||||||
// * ECIES using AES256 and HMAC-SHA-384-48
|
|
||||||
// * ECIES using AES256 and HMAC-SHA-512-64
|
|
||||||
var (
|
|
||||||
ECIES_AES128_SHA256 *ECIESParams
|
|
||||||
ECIES_AES256_SHA256 *ECIESParams
|
|
||||||
ECIES_AES256_SHA384 *ECIESParams
|
|
||||||
ECIES_AES256_SHA512 *ECIESParams
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ECIES_AES128_SHA256 = &ECIESParams{
|
|
||||||
Hash: sha256.New,
|
|
||||||
hashAlgo: crypto.SHA256,
|
|
||||||
Cipher: aes.NewCipher,
|
|
||||||
BlockSize: aes.BlockSize,
|
|
||||||
KeyLen: 16,
|
|
||||||
}
|
|
||||||
|
|
||||||
ECIES_AES256_SHA256 = &ECIESParams{
|
|
||||||
Hash: sha256.New,
|
|
||||||
hashAlgo: crypto.SHA256,
|
|
||||||
Cipher: aes.NewCipher,
|
|
||||||
BlockSize: aes.BlockSize,
|
|
||||||
KeyLen: 32,
|
|
||||||
}
|
|
||||||
|
|
||||||
ECIES_AES256_SHA384 = &ECIESParams{
|
|
||||||
Hash: sha512.New384,
|
|
||||||
hashAlgo: crypto.SHA384,
|
|
||||||
Cipher: aes.NewCipher,
|
|
||||||
BlockSize: aes.BlockSize,
|
|
||||||
KeyLen: 32,
|
|
||||||
}
|
|
||||||
|
|
||||||
ECIES_AES256_SHA512 = &ECIESParams{
|
|
||||||
Hash: sha512.New,
|
|
||||||
hashAlgo: crypto.SHA512,
|
|
||||||
Cipher: aes.NewCipher,
|
|
||||||
BlockSize: aes.BlockSize,
|
|
||||||
KeyLen: 32,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var paramsFromCurve = map[elliptic.Curve]*ECIESParams{
|
|
||||||
elliptic.P256(): ECIES_AES128_SHA256,
|
|
||||||
elliptic.P384(): ECIES_AES256_SHA384,
|
|
||||||
elliptic.P521(): ECIES_AES256_SHA512,
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddParamsForCurve(curve elliptic.Curve, params *ECIESParams) {
|
|
||||||
paramsFromCurve[curve] = params
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParamsFromCurve selects parameters optimal for the selected elliptic curve.
|
|
||||||
// Only the curves P256, P384, and P512 are supported.
|
|
||||||
func ParamsFromCurve(curve elliptic.Curve) (params *ECIESParams) {
|
|
||||||
return paramsFromCurve[curve]
|
|
||||||
|
|
||||||
/*
|
|
||||||
switch curve {
|
|
||||||
case elliptic.P256():
|
|
||||||
return ECIES_AES128_SHA256
|
|
||||||
case elliptic.P384():
|
|
||||||
return ECIES_AES256_SHA384
|
|
||||||
case elliptic.P521():
|
|
||||||
return ECIES_AES256_SHA512
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASN.1 encode the ECIES parameters relevant to the encryption operations.
|
|
||||||
func paramsToASNECIES(params *ECIESParams) (asnParams asnECIESParameters) {
|
|
||||||
if nil == params {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
asnParams.KDF = asnNISTConcatenationKDF
|
|
||||||
asnParams.MAC = hmacFull
|
|
||||||
switch params.KeyLen {
|
|
||||||
case 16:
|
|
||||||
asnParams.Sym = aes128CTRinECIES
|
|
||||||
case 24:
|
|
||||||
asnParams.Sym = aes192CTRinECIES
|
|
||||||
case 32:
|
|
||||||
asnParams.Sym = aes256CTRinECIES
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASN.1 encode the ECIES parameters relevant to ECDH.
|
|
||||||
func paramsToASNECDH(params *ECIESParams) (algo asnECDHAlgorithm) {
|
|
||||||
switch params.hashAlgo {
|
|
||||||
case crypto.SHA224:
|
|
||||||
algo = dhSinglePass_stdDH_sha224kdf
|
|
||||||
case crypto.SHA256:
|
|
||||||
algo = dhSinglePass_stdDH_sha256kdf
|
|
||||||
case crypto.SHA384:
|
|
||||||
algo = dhSinglePass_stdDH_sha384kdf
|
|
||||||
case crypto.SHA512:
|
|
||||||
algo = dhSinglePass_stdDH_sha512kdf
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASN.1 decode the ECIES parameters relevant to the encryption stage.
|
|
||||||
func asnECIEStoParams(asnParams asnECIESParameters, params *ECIESParams) {
|
|
||||||
if !asnParams.KDF.Cmp(asnNISTConcatenationKDF) {
|
|
||||||
params = nil
|
|
||||||
return
|
|
||||||
} else if !asnParams.MAC.Cmp(hmacFull) {
|
|
||||||
params = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case asnParams.Sym.Cmp(aes128CTRinECIES):
|
|
||||||
params.KeyLen = 16
|
|
||||||
params.BlockSize = 16
|
|
||||||
params.Cipher = aes.NewCipher
|
|
||||||
case asnParams.Sym.Cmp(aes192CTRinECIES):
|
|
||||||
params.KeyLen = 24
|
|
||||||
params.BlockSize = 16
|
|
||||||
params.Cipher = aes.NewCipher
|
|
||||||
case asnParams.Sym.Cmp(aes256CTRinECIES):
|
|
||||||
params.KeyLen = 32
|
|
||||||
params.BlockSize = 16
|
|
||||||
params.Cipher = aes.NewCipher
|
|
||||||
default:
|
|
||||||
params = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASN.1 decode the ECIES parameters relevant to ECDH.
|
|
||||||
func asnECDHtoParams(asnParams asnECDHAlgorithm, params *ECIESParams) {
|
|
||||||
if asnParams.Cmp(dhSinglePass_stdDH_sha224kdf) {
|
|
||||||
params.hashAlgo = crypto.SHA224
|
|
||||||
params.Hash = sha256.New224
|
|
||||||
} else if asnParams.Cmp(dhSinglePass_stdDH_sha256kdf) {
|
|
||||||
params.hashAlgo = crypto.SHA256
|
|
||||||
params.Hash = sha256.New
|
|
||||||
} else if asnParams.Cmp(dhSinglePass_stdDH_sha384kdf) {
|
|
||||||
params.hashAlgo = crypto.SHA384
|
|
||||||
params.Hash = sha512.New384
|
|
||||||
} else if asnParams.Cmp(dhSinglePass_stdDH_sha512kdf) {
|
|
||||||
params.hashAlgo = crypto.SHA512
|
|
||||||
params.Hash = sha512.New
|
|
||||||
} else {
|
|
||||||
params = nil
|
|
||||||
}
|
|
||||||
}
|
|
@ -64,6 +64,20 @@ func Dial(url_, protocol, origin string) (ws *Conn, err error) {
|
|||||||
return DialConfig(config)
|
return DialConfig(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var portMap = map[string]string{
|
||||||
|
"ws": "80",
|
||||||
|
"wss": "443",
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseAuthority(location *url.URL) string {
|
||||||
|
if _, ok := portMap[location.Scheme]; ok {
|
||||||
|
if _, _, err := net.SplitHostPort(location.Host); err != nil {
|
||||||
|
return net.JoinHostPort(location.Host, portMap[location.Scheme])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return location.Host
|
||||||
|
}
|
||||||
|
|
||||||
// DialConfig opens a new client connection to a WebSocket with a config.
|
// DialConfig opens a new client connection to a WebSocket with a config.
|
||||||
func DialConfig(config *Config) (ws *Conn, err error) {
|
func DialConfig(config *Config) (ws *Conn, err error) {
|
||||||
var client net.Conn
|
var client net.Conn
|
||||||
@ -75,10 +89,10 @@ func DialConfig(config *Config) (ws *Conn, err error) {
|
|||||||
}
|
}
|
||||||
switch config.Location.Scheme {
|
switch config.Location.Scheme {
|
||||||
case "ws":
|
case "ws":
|
||||||
client, err = net.Dial("tcp", config.Location.Host)
|
client, err = net.Dial("tcp", parseAuthority(config.Location))
|
||||||
|
|
||||||
case "wss":
|
case "wss":
|
||||||
client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig)
|
client, err = tls.Dial("tcp", parseAuthority(config.Location), config.TlsConfig)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = ErrBadScheme
|
err = ErrBadScheme
|
@ -8,7 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"code.google.com/p/go.net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This example demonstrates a trivial client.
|
// This example demonstrates a trivial client.
|
@ -8,7 +8,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.google.com/p/go.net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Echo the data received on the WebSocket.
|
// Echo the data received on the WebSocket.
|
@ -339,3 +339,76 @@ func TestSmallBuffer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var parseAuthorityTests = []struct {
|
||||||
|
in *url.URL
|
||||||
|
out string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
&url.URL{
|
||||||
|
Scheme: "ws",
|
||||||
|
Host: "www.google.com",
|
||||||
|
},
|
||||||
|
"www.google.com:80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&url.URL{
|
||||||
|
Scheme: "wss",
|
||||||
|
Host: "www.google.com",
|
||||||
|
},
|
||||||
|
"www.google.com:443",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&url.URL{
|
||||||
|
Scheme: "ws",
|
||||||
|
Host: "www.google.com:80",
|
||||||
|
},
|
||||||
|
"www.google.com:80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&url.URL{
|
||||||
|
Scheme: "wss",
|
||||||
|
Host: "www.google.com:443",
|
||||||
|
},
|
||||||
|
"www.google.com:443",
|
||||||
|
},
|
||||||
|
// some invalid ones for parseAuthority. parseAuthority doesn't
|
||||||
|
// concern itself with the scheme unless it actually knows about it
|
||||||
|
{
|
||||||
|
&url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "www.google.com",
|
||||||
|
},
|
||||||
|
"www.google.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "www.google.com:80",
|
||||||
|
},
|
||||||
|
"www.google.com:80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&url.URL{
|
||||||
|
Scheme: "asdf",
|
||||||
|
Host: "127.0.0.1",
|
||||||
|
},
|
||||||
|
"127.0.0.1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&url.URL{
|
||||||
|
Scheme: "asdf",
|
||||||
|
Host: "www.google.com",
|
||||||
|
},
|
||||||
|
"www.google.com",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseAuthority(t *testing.T) {
|
||||||
|
for _, tt := range parseAuthorityTests {
|
||||||
|
out := parseAuthority(tt.in)
|
||||||
|
if out != tt.out {
|
||||||
|
t.Errorf("got %v; want %v", out, tt.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,12 +16,12 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"code.google.com/p/go-uuid/uuid"
|
"code.google.com/p/go-uuid/uuid"
|
||||||
"code.google.com/p/go.crypto/pbkdf2"
|
|
||||||
"code.google.com/p/go.crypto/ripemd160"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/ecies"
|
"github.com/ethereum/go-ethereum/crypto/ecies"
|
||||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||||
"github.com/ethereum/go-ethereum/crypto/sha3"
|
"github.com/ethereum/go-ethereum/crypto/sha3"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
|
"golang.org/x/crypto/pbkdf2"
|
||||||
|
"golang.org/x/crypto/ripemd160"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
* @date 2015
|
* @date 2015
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This key store behaves as KeyStorePlain with the difference that
|
This key store behaves as KeyStorePlain with the difference that
|
||||||
@ -64,17 +65,18 @@ package crypto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.google.com/p/go-uuid/uuid"
|
|
||||||
"code.google.com/p/go.crypto/scrypt"
|
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
"code.google.com/p/go-uuid/uuid"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
||||||
|
"golang.org/x/crypto/scrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/obscuren/ecies"
|
"github.com/ethereum/go-ethereum/crypto/ecies"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPublicKeyEncoding(t *testing.T) {
|
func TestPublicKeyEncoding(t *testing.T) {
|
||||||
|
@ -7,9 +7,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fjl/goupnp"
|
"github.com/huin/goupnp"
|
||||||
"github.com/fjl/goupnp/dcps/internetgateway1"
|
"github.com/huin/goupnp/dcps/internetgateway1"
|
||||||
"github.com/fjl/goupnp/dcps/internetgateway2"
|
"github.com/huin/goupnp/dcps/internetgateway2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type upnp struct {
|
type upnp struct {
|
||||||
|
@ -21,10 +21,10 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.google.com/p/go.net/websocket"
|
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/xeth"
|
"github.com/ethereum/go-ethereum/xeth"
|
||||||
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
var wslogger = logger.NewLogger("RPC-WS")
|
var wslogger = logger.NewLogger("RPC-WS")
|
||||||
|
Loading…
Reference in New Issue
Block a user