From c94a2042f1be1befc1c9d69ce083f9a4224a12fc Mon Sep 17 00:00:00 2001 From: "didier.amyot" Date: Wed, 30 Jul 2014 15:02:28 -0400 Subject: [PATCH] goint there --- key.go | 40 ++++++++++++++- key_test.go | 55 ++++++++++++++++++++ main.go | 6 ++- marshal.go | 120 +++++++++++++++++++++++++++++++++++++------ marshal_test.go | 59 +++++++++++++++------ shared/permisions.go | 9 ++++ shared/shared.go | 39 ++++++++++++++ 7 files changed, 292 insertions(+), 36 deletions(-) create mode 100644 shared/permisions.go create mode 100644 shared/shared.go diff --git a/key.go b/key.go index aefef4a..713cee2 100644 --- a/key.go +++ b/key.go @@ -3,7 +3,11 @@ package main import ( "crypto/rand" "crypto/rsa" + "encoding/json" "errors" + "github.com/didiercrunch/ecrypto/shared" + "os" + "path" ) type KeyGenerator struct { @@ -11,6 +15,38 @@ type KeyGenerator struct { 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 { rsaPrivateKey, err := rsa.GenerateKey(rand.Reader, size) if err != nil { @@ -24,9 +60,9 @@ func (this *KeyGenerator) createRSAKey(size int) error { 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 { return err } - return nil + return this.saveKeys(shared.GetEcryptoDir()) } diff --git a/key_test.go b/key_test.go index 79df2c0..5f5b285 100644 --- a/key_test.go +++ b/key_test.go @@ -1,6 +1,11 @@ package main import ( + "encoding/json" + "io/ioutil" + "os" + "path" + "reflect" "testing" ) @@ -16,3 +21,53 @@ func TestCreateRSAKey(t *testing.T) { 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) + } + +} diff --git a/main.go b/main.go index 20bcb9a..50e6902 100644 --- a/main.go +++ b/main.go @@ -17,7 +17,10 @@ var createKeyCommand = cli.Command{ }, Action: func(c *cli.Context) { 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, } - fmt.Println(os.Args) app.Run(os.Args) } diff --git a/marshal.go b/marshal.go index f15c21d..9e957cc 100644 --- a/marshal.go +++ b/marshal.go @@ -2,6 +2,9 @@ package main import ( "crypto/rsa" + "encoding/json" + "errors" + "fmt" "math/big" ) @@ -12,21 +15,17 @@ const ( ) type PrivateKey struct { - Name string - Description string - Type string // rsa, el gamal,... - Version string - Key interface{} - Accept *AcceptMethods + Version string + Type string // rsa, el gamal,... + Key *RSAPrivateKey + Accept *AcceptMethods } type PublicKey struct { - Name string - Description string - Type string // rsa, el gamal,... - Version string - Key interface{} - Accept *AcceptMethods + Type string // rsa, el gamal,... + Version string + Key *RSAPublicKey + Accept *AcceptMethods } type RSAPublicKey struct { @@ -35,13 +34,102 @@ type RSAPublicKey struct { } type RSAPrivateKey struct { - N *big.Int - P *big.Int - Q *big.Int - D *big.Int + N *big.Int `json:"n,omitempty"` + P *big.Int `json:"p,omitempty"` + Q *big.Int `json:"q,omitempty"` + D *big.Int `json:"d,omitempty"` + E int `json:"e,omitempty"` +} + +type encodingRSAKey struct { + N string + P string + Q string + D string 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 { BlocCypher string BlockCypherMode string diff --git a/marshal_test.go b/marshal_test.go index c658d35..15f2e3e 100644 --- a/marshal_test.go +++ b/marshal_test.go @@ -2,7 +2,9 @@ package main import ( "crypto/rsa" + "encoding/json" "math/big" + "reflect" "testing" ) @@ -13,15 +15,11 @@ func b(x int64) *big.Int { func TestGetDefaultRSAPublicKey(t *testing.T) { key := &rsa.PublicKey{b(31 * 11), 3} pk := GetDefaultRSAPublicKey(key) - niceKey, ok := pk.Key.(*RSAPublicKey) - if !ok { - t.Error("bad key type") - return - } - if big.NewInt(31*11).Cmp(niceKey.N) != 0 { + + if big.NewInt(31*11).Cmp(pk.Key.N) != 0 { t.Error("bad N") } - if 3 != niceKey.E { + if 3 != pk.Key.E { t.Error("bad e") } } @@ -37,21 +35,50 @@ func TestGetDefaultRSAPrivateKey(t *testing.T) { if err != nil { t.Error(err) } - niceKey, ok := pk.Key.(*RSAPrivateKey) - if !ok { - t.Error("bad key type") - return - } - if niceKey.D.Int64() != 3 { + if pk.Key.D.Int64() != 3 { t.Error("bad D") } - if niceKey.E != 7 { + if pk.Key.E != 7 { t.Error("bad D") } - if niceKey.P.Int64() != 3 { + if pk.Key.P.Int64() != 3 { t.Error("bad D") } - if niceKey.Q.Int64() != 11 { + 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 + } + key2 := new(RSAPrivateKey) + if err := json.Unmarshal(data, key2); err != nil { + t.Error(err) + return + } + if !reflect.DeepEqual(key, key2) { + t.Fail() + } +} + +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() + } +} diff --git a/shared/permisions.go b/shared/permisions.go new file mode 100644 index 0000000..70f5f68 --- /dev/null +++ b/shared/permisions.go @@ -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 diff --git a/shared/shared.go b/shared/shared.go new file mode 100644 index 0000000..0bab71b --- /dev/null +++ b/shared/shared.go @@ -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 +}