commit
c1d0693cb1
49 files changed
+145
-2007
No files matched your search
Generated
+17
-29
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ImportPath": "github.com/ethereum/go-ethereum",
|
||||
"GoVersion": "go1.4",
|
||||
"GoVersion": "go1.4.1",
|
||||
"Packages": [
|
||||
"./..."
|
||||
],
|
||||
@@ -15,26 +15,6 @@
|
||||
"Comment": "null-12",
|
||||
"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",
|
||||
"Comment": "null-15",
|
||||
@@ -44,22 +24,18 @@
|
||||
"ImportPath": "github.com/ethereum/serpent-go",
|
||||
"Rev": "5767a0dbd759d313df3f404dadb7f98d7ab51443"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/fjl/goupnp",
|
||||
"Rev": "fa95df6feb61e136b499d01711fcd410ccaf20c1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/howeyc/fsnotify",
|
||||
"Comment": "v0.9.0-11-g6b1ef89",
|
||||
"Rev": "6b1ef893dc11e0447abda6da20a5203481878dda"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/jackpal/go-nat-pmp",
|
||||
"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
|
||||
"ImportPath": "github.com/huin/goupnp",
|
||||
"Rev": "4191d8a85005844ea202fde52799681971b12dfe"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/obscuren/ecies",
|
||||
"Rev": "d899334bba7bf4a157cab19d8ad836dcb1de0c34"
|
||||
"ImportPath": "github.com/jackpal/go-nat-pmp",
|
||||
"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/obscuren/otto",
|
||||
@@ -109,6 +85,18 @@
|
||||
"ImportPath": "golang.org/x/crypto/pbkdf2",
|
||||
"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",
|
||||
"Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673"
|
||||
|
||||
-77
@@ -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
@@ -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)
|
||||
}
|
||||
Generated
Vendored
File renamed without changes.
Generated
Vendored
+1
-1
@@ -3,7 +3,7 @@ goupnp is a UPnP client library for Go
|
||||
Installation
|
||||
------------
|
||||
|
||||
Run `go get -u github.com/fjl/goupnp`.
|
||||
Run `go get -u github.com/huin/goupnp`.
|
||||
|
||||
Regenerating dcps generated source code:
|
||||
----------------------------------------
|
||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/fjl/goupnp/httpu"
|
||||
"github.com/huin/goupnp/httpu"
|
||||
)
|
||||
|
||||
func main() {
|
||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/fjl/goupnp/dcps/internetgateway1"
|
||||
"github.com/huin/goupnp/dcps/internetgateway1"
|
||||
)
|
||||
|
||||
func main() {
|
||||
+2
-2
@@ -11,8 +11,8 @@ package internetgateway1
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/fjl/goupnp"
|
||||
"github.com/fjl/goupnp/soap"
|
||||
"github.com/huin/goupnp"
|
||||
"github.com/huin/goupnp/soap"
|
||||
)
|
||||
|
||||
// Hack to avoid Go complaining if time isn't used.
|
||||
+2
-2
@@ -11,8 +11,8 @@ package internetgateway2
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/fjl/goupnp"
|
||||
"github.com/fjl/goupnp/soap"
|
||||
"github.com/huin/goupnp"
|
||||
"github.com/huin/goupnp/soap"
|
||||
)
|
||||
|
||||
// Hack to avoid Go complaining if time isn't used.
|
||||
Generated
Vendored
+2
-2
@@ -8,8 +8,8 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/fjl/goupnp/scpd"
|
||||
"github.com/fjl/goupnp/soap"
|
||||
"github.com/huin/goupnp/scpd"
|
||||
"github.com/huin/goupnp/soap"
|
||||
)
|
||||
|
||||
const (
|
||||
Generated
Vendored
+1
-1
@@ -2,5 +2,5 @@
|
||||
//
|
||||
// To run examples and see the output for your local network, run the following
|
||||
// command (specifically including the -v flag):
|
||||
// go test -v github.com/fjl/goupnp/example
|
||||
// go test -v github.com/huin/goupnp/example
|
||||
package example
|
||||
Generated
Vendored
+2
-2
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fjl/goupnp"
|
||||
"github.com/fjl/goupnp/dcps/internetgateway1"
|
||||
"github.com/huin/goupnp"
|
||||
"github.com/huin/goupnp/dcps/internetgateway1"
|
||||
)
|
||||
|
||||
// Use discovered WANPPPConnection1 services to find external IP addresses.
|
||||
Generated
Vendored
+5
-5
@@ -17,8 +17,8 @@ import (
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/fjl/goupnp"
|
||||
"github.com/fjl/goupnp/scpd"
|
||||
"github.com/huin/goupnp"
|
||||
"github.com/huin/goupnp/scpd"
|
||||
"github.com/huin/goutil/codegen"
|
||||
"github.com/jingweno/gotask/tasking"
|
||||
)
|
||||
@@ -38,7 +38,7 @@ var (
|
||||
// -s, --spec_filename=<upnpresources.zip>
|
||||
// Path to the specification file, available from http://upnp.org/resources/upnpresources.zip
|
||||
// -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
|
||||
// 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) {
|
||||
@@ -445,8 +445,8 @@ package {{$name}}
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/fjl/goupnp"
|
||||
"github.com/fjl/goupnp/soap"
|
||||
"github.com/huin/goupnp"
|
||||
"github.com/huin/goupnp/soap"
|
||||
)
|
||||
|
||||
// Hack to avoid Go complaining if time isn't used.
|
||||
Generated
Vendored
+5
-5
@@ -1,11 +1,11 @@
|
||||
// goupnp is an implementation of a client for various UPnP services.
|
||||
//
|
||||
// For most uses, it is recommended to use the code-generated packages under
|
||||
// github.com/fjl/goupnp/dcps. Example use is shown at
|
||||
// http://godoc.org/github.com/fjl/goupnp/example
|
||||
// github.com/huin/goupnp/dcps. Example use is shown at
|
||||
// http://godoc.org/github.com/huin/goupnp/example
|
||||
//
|
||||
// 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
|
||||
// UPnP example XML specifications. Not all methods will work on these clients,
|
||||
@@ -20,8 +20,8 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/fjl/goupnp/httpu"
|
||||
"github.com/fjl/goupnp/ssdp"
|
||||
"github.com/huin/goupnp/httpu"
|
||||
"github.com/huin/goupnp/ssdp"
|
||||
)
|
||||
|
||||
// ContextError is an error that wraps an error with some context information.
|
||||
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
+1
-2
@@ -2,8 +2,7 @@ package goupnp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fjl/goupnp/soap"
|
||||
"github.com/huin/goupnp/soap"
|
||||
)
|
||||
|
||||
// ServiceClient is a SOAP client, root device and the service for the SOAP
|
||||
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
+1
-1
@@ -10,7 +10,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fjl/goupnp/httpu"
|
||||
"github.com/huin/goupnp/httpu"
|
||||
)
|
||||
|
||||
const (
|
||||
Generated
Vendored
+1
-1
@@ -8,7 +8,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/fjl/goupnp/httpu"
|
||||
"github.com/huin/goupnp/httpu"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
+16
-2
@@ -64,6 +64,20 @@ func Dial(url_, protocol, origin string) (ws *Conn, err error) {
|
||||
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.
|
||||
func DialConfig(config *Config) (ws *Conn, err error) {
|
||||
var client net.Conn
|
||||
@@ -75,10 +89,10 @@ func DialConfig(config *Config) (ws *Conn, err error) {
|
||||
}
|
||||
switch config.Location.Scheme {
|
||||
case "ws":
|
||||
client, err = net.Dial("tcp", config.Location.Host)
|
||||
client, err = net.Dial("tcp", parseAuthority(config.Location))
|
||||
|
||||
case "wss":
|
||||
client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig)
|
||||
client, err = tls.Dial("tcp", parseAuthority(config.Location), config.TlsConfig)
|
||||
|
||||
default:
|
||||
err = ErrBadScheme
|
||||
Generated
Vendored
+1
-1
@@ -8,7 +8,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"code.google.com/p/go.net/websocket"
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
// This example demonstrates a trivial client.
|
||||
Generated
Vendored
+1
-1
@@ -8,7 +8,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"code.google.com/p/go.net/websocket"
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
// Echo the data received on the WebSocket.
|
||||
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
+73
@@ -339,3 +339,76 @@ func TestSmallBuffer(t *testing.T) {
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -16,12 +16,12 @@ import (
|
||||
"errors"
|
||||
|
||||
"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/secp256k1"
|
||||
"github.com/ethereum/go-ethereum/crypto/sha3"
|
||||
"github.com/ethereum/go-ethereum/ethutil"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
* @date 2015
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This key store behaves as KeyStorePlain with the difference that
|
||||
@@ -64,17 +65,18 @@ package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/go-uuid/uuid"
|
||||
"code.google.com/p/go.crypto/scrypt"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"code.google.com/p/go-uuid/uuid"
|
||||
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
||||
"golang.org/x/crypto/scrypt"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/obscuren/ecies"
|
||||
"github.com/ethereum/go-ethereum/crypto/ecies"
|
||||
)
|
||||
|
||||
func TestPublicKeyEncoding(t *testing.T) {
|
||||
|
||||
+3
-3
@@ -7,9 +7,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fjl/goupnp"
|
||||
"github.com/fjl/goupnp/dcps/internetgateway1"
|
||||
"github.com/fjl/goupnp/dcps/internetgateway2"
|
||||
"github.com/huin/goupnp"
|
||||
"github.com/huin/goupnp/dcps/internetgateway1"
|
||||
"github.com/huin/goupnp/dcps/internetgateway2"
|
||||
)
|
||||
|
||||
type upnp struct {
|
||||
|
||||
+1
-1
@@ -21,10 +21,10 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"code.google.com/p/go.net/websocket"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/xeth"
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
var wslogger = logger.NewLogger("RPC-WS")
|
||||
|
||||
Reference in new issue
Block a user