goint there
This commit is contained in:
1 parent
776c73b91c
commit
c94a2042f1
7 files changed
+289
-33
No files matched your search
@@ -3,7 +3,11 @@ package main
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/didiercrunch/ecrypto/shared"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
type KeyGenerator struct {
|
type KeyGenerator struct {
|
||||||
@@ -11,6 +15,38 @@ type KeyGenerator struct {
|
|||||||
privateKey *PrivateKey
|
privateKey *PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *KeyGenerator) ensureDirectoryExists(dir string) error {
|
||||||
|
stat, err := os.Stat(dir)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return os.Mkdir(dir, 0700)
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
} else if !stat.IsDir() {
|
||||||
|
return errors.New(dir + " is not a directory")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *KeyGenerator) saveKeyAsJSON(key interface{}, filepath string) error {
|
||||||
|
w, err := os.Create(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
enc := json.NewEncoder(w)
|
||||||
|
return enc.Encode(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *KeyGenerator) saveKeys(dirPath string) error {
|
||||||
|
if err := this.ensureDirectoryExists(dirPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := this.saveKeyAsJSON(this.publicKey, path.Join(dirPath, "publickey.json")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return this.saveKeyAsJSON(this.privateKey, path.Join(dirPath, "privatekey.json"))
|
||||||
|
}
|
||||||
|
|
||||||
func (this *KeyGenerator) createRSAKey(size int) error {
|
func (this *KeyGenerator) createRSAKey(size int) error {
|
||||||
rsaPrivateKey, err := rsa.GenerateKey(rand.Reader, size)
|
rsaPrivateKey, err := rsa.GenerateKey(rand.Reader, size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -24,9 +60,9 @@ func (this *KeyGenerator) createRSAKey(size int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *KeyGenerator) CreateNewKey(size int, password string) error {
|
func (this *KeyGenerator) CreateNewKey(size int) error {
|
||||||
if err := this.createRSAKey(size); err != nil {
|
if err := this.createRSAKey(size); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return this.saveKeys(shared.GetEcryptoDir())
|
||||||
}
|
}
|
||||||
+55
@@ -1,6 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,3 +21,53 @@ func TestCreateRSAKey(t *testing.T) {
|
|||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSaveKeyAsJSON(t *testing.T) {
|
||||||
|
kc := new(KeyGenerator)
|
||||||
|
if err := kc.CreateNewKey(100); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file, err := ioutil.TempFile(os.TempDir(), "prefix")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.Remove(file.Name())
|
||||||
|
if err := kc.saveKeyAsJSON(kc.privateKey, file.Name()); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
data, err := ioutil.ReadFile(file.Name())
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pk := new(PrivateKey)
|
||||||
|
if err := json.Unmarshal(data, pk); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(pk.Key, kc.privateKey.Key) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnsureDirectoryExists(t *testing.T) {
|
||||||
|
kc := new(KeyGenerator)
|
||||||
|
fooDir := path.Join(os.TempDir(), "fds89d")
|
||||||
|
defer os.Remove(fooDir)
|
||||||
|
if err := kc.ensureDirectoryExists(fooDir); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(fooDir); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := kc.ensureDirectoryExists(fooDir); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,7 +17,10 @@ var createKeyCommand = cli.Command{
|
|||||||
},
|
},
|
||||||
Action: func(c *cli.Context) {
|
Action: func(c *cli.Context) {
|
||||||
keyGenerator := new(KeyGenerator)
|
keyGenerator := new(KeyGenerator)
|
||||||
keyGenerator.CreateNewKey(c.Int("size"), c.String("password"))
|
fmt.Println("creating key")
|
||||||
|
if err := keyGenerator.CreateNewKey(c.Int("size")); err != nil {
|
||||||
|
fmt.Println("error while creating the key\n", err)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +32,5 @@ func main() {
|
|||||||
createKeyCommand,
|
createKeyCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(os.Args)
|
|
||||||
app.Run(os.Args)
|
app.Run(os.Args)
|
||||||
}
|
}
|
||||||
+99
-11
@@ -2,6 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,20 +15,16 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type PrivateKey struct {
|
type PrivateKey struct {
|
||||||
Name string
|
|
||||||
Description string
|
|
||||||
Type string // rsa, el gamal,...
|
|
||||||
Version string
|
Version string
|
||||||
Key interface{}
|
Type string // rsa, el gamal,...
|
||||||
|
Key *RSAPrivateKey
|
||||||
Accept *AcceptMethods
|
Accept *AcceptMethods
|
||||||
}
|
}
|
||||||
|
|
||||||
type PublicKey struct {
|
type PublicKey struct {
|
||||||
Name string
|
|
||||||
Description string
|
|
||||||
Type string // rsa, el gamal,...
|
Type string // rsa, el gamal,...
|
||||||
Version string
|
Version string
|
||||||
Key interface{}
|
Key *RSAPublicKey
|
||||||
Accept *AcceptMethods
|
Accept *AcceptMethods
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,13 +34,102 @@ type RSAPublicKey struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RSAPrivateKey struct {
|
type RSAPrivateKey struct {
|
||||||
N *big.Int
|
N *big.Int `json:"n,omitempty"`
|
||||||
P *big.Int
|
P *big.Int `json:"p,omitempty"`
|
||||||
Q *big.Int
|
Q *big.Int `json:"q,omitempty"`
|
||||||
D *big.Int
|
D *big.Int `json:"d,omitempty"`
|
||||||
|
E int `json:"e,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type encodingRSAKey struct {
|
||||||
|
N string
|
||||||
|
P string
|
||||||
|
Q string
|
||||||
|
D string
|
||||||
E int
|
E int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *encodingRSAKey) CreateFromRSAPrivateKey(key *RSAPrivateKey) *encodingRSAKey {
|
||||||
|
this.N = fmt.Sprintf("%x", key.N)
|
||||||
|
this.P = fmt.Sprintf("%x", key.P)
|
||||||
|
this.Q = fmt.Sprintf("%x", key.Q)
|
||||||
|
this.D = fmt.Sprintf("%x", key.D)
|
||||||
|
this.E = key.E
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *encodingRSAKey) CreateFromRSAPublicKey(key *RSAPublicKey) *encodingRSAKey {
|
||||||
|
this.N = fmt.Sprintf("%x", key.N)
|
||||||
|
this.E = key.E
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *encodingRSAKey) SetRSAPrivateKey(key *RSAPrivateKey) (*RSAPrivateKey, error) {
|
||||||
|
if i, ok := new(big.Int).SetString(this.N, 16); !ok {
|
||||||
|
return nil, errors.New("cannot parse string has hexadecimal string")
|
||||||
|
} else {
|
||||||
|
key.N = i
|
||||||
|
}
|
||||||
|
|
||||||
|
if i, ok := new(big.Int).SetString(this.P, 16); !ok {
|
||||||
|
return nil, errors.New("cannot parse string has hexadecimal string")
|
||||||
|
} else {
|
||||||
|
key.P = i
|
||||||
|
}
|
||||||
|
|
||||||
|
if i, ok := new(big.Int).SetString(this.Q, 16); !ok {
|
||||||
|
return nil, errors.New("cannot parse string has hexadecimal string")
|
||||||
|
} else {
|
||||||
|
key.Q = i
|
||||||
|
}
|
||||||
|
|
||||||
|
if i, ok := new(big.Int).SetString(this.D, 16); !ok {
|
||||||
|
return nil, errors.New("cannot parse string has hexadecimal string")
|
||||||
|
} else {
|
||||||
|
key.D = i
|
||||||
|
}
|
||||||
|
key.E = this.E
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *encodingRSAKey) SetRSAPublicKey(key *RSAPublicKey) (*RSAPublicKey, error) {
|
||||||
|
if i, ok := new(big.Int).SetString(this.N, 16); !ok {
|
||||||
|
return nil, errors.New("cannot parse string has hexadecimal string")
|
||||||
|
} else {
|
||||||
|
key.N = i
|
||||||
|
}
|
||||||
|
key.E = this.E
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RSAPrivateKey) MarshalJSON() ([]byte, error) {
|
||||||
|
e := new(encodingRSAKey)
|
||||||
|
return json.Marshal(e.CreateFromRSAPrivateKey(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RSAPrivateKey) UnmarshalJSON(data []byte) error {
|
||||||
|
obj := new(encodingRSAKey)
|
||||||
|
if err := json.Unmarshal(data, obj); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := obj.SetRSAPrivateKey(this)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RSAPublicKey) MarshalJSON() ([]byte, error) {
|
||||||
|
e := new(encodingRSAKey)
|
||||||
|
return json.Marshal(e.CreateFromRSAPublicKey(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RSAPublicKey) UnmarshalJSON(data []byte) error {
|
||||||
|
obj := new(encodingRSAKey)
|
||||||
|
if err := json.Unmarshal(data, obj); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err := obj.SetRSAPublicKey(this)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
type AcceptMethods struct {
|
type AcceptMethods struct {
|
||||||
BlocCypher string
|
BlocCypher string
|
||||||
BlockCypherMode string
|
BlockCypherMode string
|
||||||
|
|||||||
+45
-18
@@ -2,7 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"encoding/json"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,15 +15,11 @@ func b(x int64) *big.Int {
|
|||||||
func TestGetDefaultRSAPublicKey(t *testing.T) {
|
func TestGetDefaultRSAPublicKey(t *testing.T) {
|
||||||
key := &rsa.PublicKey{b(31 * 11), 3}
|
key := &rsa.PublicKey{b(31 * 11), 3}
|
||||||
pk := GetDefaultRSAPublicKey(key)
|
pk := GetDefaultRSAPublicKey(key)
|
||||||
niceKey, ok := pk.Key.(*RSAPublicKey)
|
|
||||||
if !ok {
|
if big.NewInt(31*11).Cmp(pk.Key.N) != 0 {
|
||||||
t.Error("bad key type")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if big.NewInt(31*11).Cmp(niceKey.N) != 0 {
|
|
||||||
t.Error("bad N")
|
t.Error("bad N")
|
||||||
}
|
}
|
||||||
if 3 != niceKey.E {
|
if 3 != pk.Key.E {
|
||||||
t.Error("bad e")
|
t.Error("bad e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,21 +35,50 @@ func TestGetDefaultRSAPrivateKey(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
niceKey, ok := pk.Key.(*RSAPrivateKey)
|
if pk.Key.D.Int64() != 3 {
|
||||||
if !ok {
|
t.Error("bad D")
|
||||||
t.Error("bad key type")
|
}
|
||||||
|
if pk.Key.E != 7 {
|
||||||
|
t.Error("bad D")
|
||||||
|
}
|
||||||
|
if pk.Key.P.Int64() != 3 {
|
||||||
|
t.Error("bad D")
|
||||||
|
}
|
||||||
|
if pk.Key.Q.Int64() != 11 {
|
||||||
|
t.Error("bad D")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRSAPrivateKeyJsonification(t *testing.T) {
|
||||||
|
key := &RSAPrivateKey{b(1023), b(2112), b(328723), b(2332), 89}
|
||||||
|
data, err := json.Marshal(key)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if niceKey.D.Int64() != 3 {
|
key2 := new(RSAPrivateKey)
|
||||||
t.Error("bad D")
|
if err := json.Unmarshal(data, key2); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if niceKey.E != 7 {
|
if !reflect.DeepEqual(key, key2) {
|
||||||
t.Error("bad D")
|
t.Fail()
|
||||||
}
|
}
|
||||||
if niceKey.P.Int64() != 3 {
|
|
||||||
t.Error("bad D")
|
|
||||||
}
|
}
|
||||||
if niceKey.Q.Int64() != 11 {
|
|
||||||
t.Error("bad D")
|
func TestRSAPublicKeyJsonification(t *testing.T) {
|
||||||
|
key := &RSAPublicKey{b(1023), 89}
|
||||||
|
data, err := json.Marshal(key)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
key2 := new(RSAPublicKey)
|
||||||
|
if err := json.Unmarshal(data, key2); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(key, key2) {
|
||||||
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package shared
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const DIRECTORY_PERMISSION os.FileMode = 0700
|
||||||
|
const PUBLIC_KEY_PERMISSION os.FileMode = 0644
|
||||||
|
const PRIVATE_KEY_PERMISSION os.FileMode = 0600
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package shared
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ecryptoDir string
|
||||||
|
|
||||||
|
func ensureEcryptoDirectoryIsOkay(dir string) error {
|
||||||
|
stat, err := os.Stat(dir)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return os.Mkdir(dir, DIRECTORY_PERMISSION)
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
} else if !stat.IsDir() {
|
||||||
|
return errors.New(dir + " is not a directory")
|
||||||
|
} else if perm := stat.Mode().Perm(); perm != DIRECTORY_PERMISSION {
|
||||||
|
msg := fmt.Sprintf("root folder has bad file permission. should be set to %v but vas %v", DIRECTORY_PERMISSION, perm)
|
||||||
|
return errors.New(msg)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ecryptoDir = path.Join(os.Getenv("HOME"), ".ecrypto")
|
||||||
|
if err := ensureEcryptoDirectoryIsOkay(ecryptoDir); err != nil {
|
||||||
|
fmt.Println("cannot work with eCrypto directory", err)
|
||||||
|
os.Exit(1)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetEcryptoDir() string {
|
||||||
|
return ecryptoDir
|
||||||
|
}
|
||||||
Reference in new issue
Block a user