diff --git a/.goxc.json b/.goxc.json index 78c96b2..dd5887c 100644 --- a/.goxc.json +++ b/.goxc.json @@ -1,5 +1,5 @@ { - "PackageVersion": "0.0.0", + "PackageVersion": "0.0.1", "PrereleaseInfo": "ecrypto", "ConfigVersion": "0.9", "Arch": "386,amd64", diff --git a/key.go b/key.go new file mode 100644 index 0000000..aefef4a --- /dev/null +++ b/key.go @@ -0,0 +1,32 @@ +package main + +import ( + "crypto/rand" + "crypto/rsa" + "errors" +) + +type KeyGenerator struct { + publicKey *PublicKey + privateKey *PrivateKey +} + +func (this *KeyGenerator) createRSAKey(size int) error { + rsaPrivateKey, err := rsa.GenerateKey(rand.Reader, size) + if err != nil { + return errors.New("cannot generate the rsa public/private key pair\n" + err.Error()) + } + + if this.privateKey, err = GetDefaultRSAPrivateKey(rsaPrivateKey); err != nil { + return errors.New("cannot generate the rsa public/private key pair\n" + err.Error()) + } + this.publicKey = GetDefaultRSAPublicKey(&rsaPrivateKey.PublicKey) + return nil +} + +func (this *KeyGenerator) CreateNewKey(size int, password string) error { + if err := this.createRSAKey(size); err != nil { + return err + } + return nil +} diff --git a/key_test.go b/key_test.go new file mode 100644 index 0000000..79df2c0 --- /dev/null +++ b/key_test.go @@ -0,0 +1,18 @@ +package main + +import ( + "testing" +) + +func TestCreateRSAKey(t *testing.T) { + kc := new(KeyGenerator) + if err := kc.createRSAKey(100); err != nil { + t.Error(err) + } + if kc.privateKey == nil { + t.Fail() + } + if kc.publicKey == nil { + t.Fail() + } +} diff --git a/main.go b/main.go index 52a7925..20bcb9a 100644 --- a/main.go +++ b/main.go @@ -2,8 +2,33 @@ package main import ( "fmt" + "github.com/codegangsta/cli" + "os" ) +const VERSION = "0.0.1" + +var createKeyCommand = cli.Command{ + Name: "createkey", + Usage: "create a pair of public/private key", + Flags: []cli.Flag{ + cli.IntFlag{Name: "size, s", Value: 2048, Usage: "key size in bits"}, + cli.StringFlag{Name: "password, p", Value: "", Usage: "password to access the private key"}, + }, + Action: func(c *cli.Context) { + keyGenerator := new(KeyGenerator) + keyGenerator.CreateNewKey(c.Int("size"), c.String("password")) + }, +} + func main() { - fmt.Println("hello world") + app := cli.NewApp() + app.Name = "ecrypto" + app.Usage = "encrypt files" + app.Commands = []cli.Command{ + createKeyCommand, + } + + fmt.Println(os.Args) + app.Run(os.Args) } diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..22326b0 --- /dev/null +++ b/main_test.go @@ -0,0 +1,27 @@ +package main + +import ( + "github.com/codegangsta/cli" + "testing" +) + +func TestCreateKeyCommand(t *testing.T) { + c := createKeyCommand + hasBeenCalled := false + c.Action = func(c *cli.Context) { + if c.Int("size") != 22 { + t.Error("wrong size") + } + if c.String("password") != "money" { + t.Error("wrong password") + } + hasBeenCalled = true + } + app := cli.NewApp() + app.Commands = []cli.Command{c} + args := []string{"file", "createkey", "-size", "22", "-password", "money"} + app.Run(args) + if !hasBeenCalled { + t.Error("sub command *createkey* has not been called") + } +} diff --git a/marshal.go b/marshal.go new file mode 100644 index 0000000..f15c21d --- /dev/null +++ b/marshal.go @@ -0,0 +1,72 @@ +package main + +import ( + "crypto/rsa" + "math/big" +) + +const ( + DEFAULT_BLOCK_CYPHER = "AES" + DEFAULT_BLOCK_CYPHER_MODE = "CBC" + DEFAULT_HASH_FUNCTION = "SHA256" +) + +type PrivateKey struct { + Name string + Description string + Type string // rsa, el gamal,... + Version string + Key interface{} + Accept *AcceptMethods +} + +type PublicKey struct { + Name string + Description string + Type string // rsa, el gamal,... + Version string + Key interface{} + Accept *AcceptMethods +} + +type RSAPublicKey struct { + N *big.Int + E int +} + +type RSAPrivateKey struct { + N *big.Int + P *big.Int + Q *big.Int + D *big.Int + E int +} + +type AcceptMethods struct { + BlocCypher string + BlockCypherMode string + HashFunction string +} + +func GetDefaultRSAPublicKey(publicKey *rsa.PublicKey) *PublicKey { + key := &RSAPublicKey{publicKey.N, publicKey.E} + accept := &AcceptMethods{ + DEFAULT_BLOCK_CYPHER, + DEFAULT_BLOCK_CYPHER_MODE, + DEFAULT_HASH_FUNCTION, + } + return &PublicKey{Type: "RSA", Version: VERSION, Key: key, Accept: accept} +} + +func GetDefaultRSAPrivateKey(publicKey *rsa.PrivateKey) (*PrivateKey, error) { + if err := publicKey.Validate(); err != nil { + return nil, err + } + key := &RSAPrivateKey{publicKey.N, publicKey.Primes[0], publicKey.Primes[1], publicKey.D, publicKey.E} + accept := &AcceptMethods{ + DEFAULT_BLOCK_CYPHER, + DEFAULT_BLOCK_CYPHER_MODE, + DEFAULT_HASH_FUNCTION, + } + return &PrivateKey{Type: "RSA", Version: VERSION, Key: key, Accept: accept}, nil +} diff --git a/marshal_test.go b/marshal_test.go new file mode 100644 index 0000000..c658d35 --- /dev/null +++ b/marshal_test.go @@ -0,0 +1,57 @@ +package main + +import ( + "crypto/rsa" + "math/big" + "testing" +) + +func b(x int64) *big.Int { + return big.NewInt(x) +} + +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 { + t.Error("bad N") + } + if 3 != niceKey.E { + t.Error("bad e") + } +} + +func TestGetDefaultRSAPrivateKey(t *testing.T) { + privKey := &rsa.PrivateKey{ + rsa.PublicKey{b(3 * 11), 7}, + b(3), + []*big.Int{b(3), b(11)}, + rsa.PrecomputedValues{}, + } + pk, err := GetDefaultRSAPrivateKey(privKey) + if err != nil { + t.Error(err) + } + niceKey, ok := pk.Key.(*RSAPrivateKey) + if !ok { + t.Error("bad key type") + return + } + if niceKey.D.Int64() != 3 { + t.Error("bad D") + } + if niceKey.E != 7 { + t.Error("bad D") + } + if niceKey.P.Int64() != 3 { + t.Error("bad D") + } + if niceKey.Q.Int64() != 11 { + t.Error("bad D") + } +}