diff --git a/ecdsa.go b/ecdsa.go index f8f51b2..6754ee4 100644 --- a/ecdsa.go +++ b/ecdsa.go @@ -6,8 +6,10 @@ import ( "crypto/elliptic" "crypto/rand" "crypto/x509" + "encoding/asn1" "encoding/pem" "errors" + "math/big" ) const ( @@ -24,6 +26,10 @@ type ( EcdsaPublicKey struct { public_key *ecdsa.PublicKey } + + signatureEcdsa struct { + R, S *big.Int + } ) // generate a new ecdsa private key @@ -46,8 +52,14 @@ func (pr EcdsaPrivateKey) Public() PublicKey { } // sign a message with the private key -func (pr EcdsaPrivateKey) Sign(message []byte) ([]byte, error) { - return make([]byte, 0), errors.New("not implemented yet!") +func (pr EcdsaPrivateKey) Sign(message []byte, hash crypto.Hash) ([]byte, error) { + empty := make([]byte, 0) + if !hash.Available() { + return empty, errors.New("Hash method is not available!") + } + hashed_message := hash.New() + hashed_message.Write(message) + return pr.private_key.Sign(rand.Reader, hashed_message.Sum(nil), hash) } // get the private key @@ -72,6 +84,11 @@ func (pu *EcdsaPublicKey) MarshalPem() (marshalledPemBlock, error) { } // verify a message using the ecdsa public key -func (pu *EcdsaPublicKey) Verify(message []byte, signature []byte) (bool, error) { - return false, errors.New("not implemented yet!") +func (pu *EcdsaPublicKey) Verify(message []byte, signature_raw []byte, hash crypto.Hash) (bool, error) { + var sig signatureEcdsa + _, err := asn1.Unmarshal(signature_raw, &sig) + if err != nil { return false, err } + hashed_message := hash.New() + hashed_message.Write(message) + return ecdsa.Verify(pu.public_key, hashed_message.Sum(nil), sig.R, sig.S), nil } diff --git a/private_key_test.go b/private_key_test.go index 1d8f5ba..a563f50 100644 --- a/private_key_test.go +++ b/private_key_test.go @@ -1,6 +1,7 @@ package pki import ( + "crypto" "crypto/elliptic" "encoding/pem" "testing" @@ -8,6 +9,7 @@ import ( var ( SignatureMessage = []byte("foobar") + SignatureHash = crypto.SHA512 ) // run the marshal test @@ -34,10 +36,10 @@ func RunPrivateKeyTests(pk_type string, pk PrivateKey, t *testing.T) { _, err := RunMarshalTest(pk_type + "-public", pu, PemLabelPublic, t) if err != nil { return } - signature, err := pk.Sign(SignatureMessage) + signature, err := pk.Sign(SignatureMessage, SignatureHash) if err != nil { t.Errorf("%s: error creating a signature: %s", pk_type, err) } - valid, err := pu.Verify(SignatureMessage, signature) + valid, err := pu.Verify(SignatureMessage, signature, SignatureHash) if err != nil { t.Errorf("%s: could not verify message: %s", pk_type, err) } if !valid { t.Errorf("%s: signature invalid, but should be valid!", pk_type) } } diff --git a/rsa.go b/rsa.go index 71acd55..9a4f298 100644 --- a/rsa.go +++ b/rsa.go @@ -41,7 +41,7 @@ func (pr *RsaPrivateKey) Public() PublicKey { return &RsaPublicKey{pr.private_key.Public().(*rsa.PublicKey)} } -func (pr RsaPrivateKey) Sign(message []byte) ([]byte, error) { +func (pr RsaPrivateKey) Sign(message []byte, hash crypto.Hash) ([]byte, error) { return make([]byte, 0), errors.New("not implemented yet!") } @@ -63,6 +63,6 @@ func (pu *RsaPublicKey) MarshalPem() (marshalledPemBlock, error) { return pem.EncodeToMemory(&pem_block), nil } -func (pu *RsaPublicKey) Verify(message []byte, signature []byte) (bool, error) { +func (pu *RsaPublicKey) Verify(message []byte, signature []byte, hash crypto.Hash) (bool, error) { return false, errors.New("not implemented yet!") } diff --git a/types.go b/types.go index b05bd40..22c35d4 100644 --- a/types.go +++ b/types.go @@ -14,8 +14,10 @@ type ( PrivateKey interface { // derive a public key from the private key Public() PublicKey - // sign a message with the private key - Sign(message []byte) ([]byte, error) + // Sign a message using the public key and the given hash method. + // To use a hash method, include the package + // import _ "crypto/sha512" + Sign(message []byte, hash crypto.Hash) ([]byte, error) // return the private key structure privateKey() crypto.PrivateKey @@ -25,7 +27,7 @@ type ( PublicKey interface { Pemmer // use the public key to verify a message against a signature - Verify(message []byte, signature []byte) (bool, error) + Verify(message []byte, signature []byte, hash crypto.Hash) (bool, error) } Pemmer interface {