Documentation ¶
Overview ¶
Package ecc makes public key elliptic curve cryptography easier to use. Cryptographic functions are from "crypto/ecdsa" and "github.com/cloudflare/redoctober/ecdh".
Sign/Verify // authentication by signing a hash SignMessage/VerifyMessage // authentication by hashing a message and signing the hash SHA256 Encrypt/Decrypt // encrypts with ephemeral symmetrical key AES-128-CBC-HMAC-SHA1 Seal/Open // both Sign and Encrypt, then Decrypt and Verify Marshal/Unmarshal // convert keys to and from []byte slices PEM/DecodePEM // keys in PEM file format, can be encrypted with a password
Packages ecdh, padding and symcrypt are copied from redoctober into this package so it works with go get. Only a few minor changes were made: package import paths, an error check and a comment added. Run ./diff_redoctober.sh to see all changes.
Example (Encrypt) ¶
package main import ( "crypto/elliptic" "fmt" "gitlab.com/elktree/ecc" ) func main() { // create keys pub, priv, _ := ecc.GenerateKeys(elliptic.P521()) plaintext := "secret secrets are no fun, secret secrets hurt someone" // use public key to encrypt encrypted, _ := pub.Encrypt([]byte(plaintext)) fmt.Println(len(encrypted)) // use private key to decrypt decrypted, _ := priv.Decrypt(encrypted) fmt.Println(string(decrypted)) }
Output: 234 secret secrets are no fun, secret secrets hurt someone
Example (EncyptedPEM) ¶
package main import ( "fmt" "gitlab.com/elktree/ecc" ) func main() { const encryptedPem = ` -----BEGIN EC PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-256-CBC,94853fd16a027c0c07663ffc09cc32e6 cclqDp6HTJD/xB/nk3fDBDJLnSohMLnsjasx4l8QaD0hMICg/r4gtPHuzDHwxLGA GHNahxeZkDYq/RutOjcihihC5FKdJJZ1b88EnXoprG7Kp2iwbPteD6mbzWqxwpbJ aP0xnZAk+xghjHb9v/qxG2lFho/JpGIek8SfDLX5eH0= -----END EC PRIVATE KEY----- ` // load private key with password "abc123" priv, _ := ecc.DecodePEMPrivateKey([]byte(encryptedPem), "abc123") // get PEM without encryption; password is blank plainPem, _ := priv.PEM("") fmt.Println(string(plainPem)) }
Output: -----BEGIN EC PRIVATE KEY----- MHcCAQEEIFtZ6cvIvTN2yGlL/VDL0hfQCrui+wEg5/kt6X1KgfiBoAoGCCqGSM49 AwEHoUQDQgAE9rgmY7NQAqt4r3o2Bt4ViS8HWlHHJ+Ig2VIpRaxUyMrrZma9hHu5 SvdpYhDA1fClYKw0ZEKkuZ5xZFtCJ4/MkQ== -----END EC PRIVATE KEY-----
Example (Marshal) ¶
package main import ( "crypto/elliptic" "fmt" "gitlab.com/elktree/ecc" ) func main() { const privPem = ` -----BEGIN EC PRIVATE KEY----- MHcCAQEEIFtZ6cvIvTN2yGlL/VDL0hfQCrui+wEg5/kt6X1KgfiBoAoGCCqGSM49 AwEHoUQDQgAE9rgmY7NQAqt4r3o2Bt4ViS8HWlHHJ+Ig2VIpRaxUyMrrZma9hHu5 SvdpYhDA1fClYKw0ZEKkuZ5xZFtCJ4/MkQ== -----END EC PRIVATE KEY----- ` // load keys (the private key contains the public key) priv, _ := ecc.DecodePEMPrivateKey([]byte(privPem), "") // ecc.Keys are wrappers around ecdsa.Keys pub := ecc.PublicKey{Key: &priv.Key.PublicKey} // A single byte (x04) is prefixed to the raw public key bytes when marshalled, // indicating that the key is uncompressed. This makes a P-256 public key 65 // bytes instead of 32 bytes for X and 32 bytes for Y. pubMarshalled := pub.Marshal() fmt.Printf("public key len(%d): %x...\n", len(pubMarshalled), pubMarshalled[:20]) // Marshaled private key (in x509 ASN.1, DER format) is 121 bytes. It stores // the 32 bytes of private key, 65 bytes of public key, the curve ID and a // version number. privMarshalled, _ := priv.Marshal() fmt.Printf("private key len(%d): %x...\n", len(privMarshalled), privMarshalled[:20]) priv2, _ := ecc.UnmarshalPrivateKey(privMarshalled) fmt.Println(priv2.Key.Params().Name) pub2 := ecc.UnmarshalPublicKey(elliptic.P256(), pubMarshalled) fmt.Println(&pub == pub2) // false. same values but not the same pointers }
Output: public key len(65): 04f6b82663b35002ab78af7a3606de15892f075a... private key len(121): 307702010104205b59e9cbc8bd3376c8694bfd50... P-256 false
Example (PEM) ¶
package main import ( "fmt" "gitlab.com/elktree/ecc" ) func main() { const privPem = ` -----BEGIN EC PRIVATE KEY----- MIGkAgEBBDAED2R9NFkyj4E5ITbx20iSiYyHVxvxl7awC1aPfZ49KunnssO97+07 R7qyhIUZ6aCgBwYFK4EEACKhZANiAAShYa1f7DltZ2tDBHs6MdgMt3MV8u0DOIC+ ZZ3LjvP5corPnvkXgJI/0np63Zm09KsEbK/JB/tL6Lzp30ROxRbmOuxGSbL353jD zaXKbGmizJi2+Vr/0BQKXEM0h2laHDU= -----END EC PRIVATE KEY----- ` // load keys (the private key contains the public key) priv, _ := ecc.DecodePEMPrivateKey([]byte(privPem), "") // ecc.Keys are wrappers around ecdsa.Keys pub := ecc.PublicKey{Key: &priv.Key.PublicKey} // get public key in PEM format pubPem, _ := pub.PEM() fmt.Println(string(pubPem)) }
Output: -----BEGIN PUBLIC KEY----- MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEoWGtX+w5bWdrQwR7OjHYDLdzFfLtAziA vmWdy47z+XKKz575F4CSP9J6et2ZtPSrBGyvyQf7S+i86d9ETsUW5jrsRkmy9+d4 w82lymxposyYtvla/9AUClxDNIdpWhw1 -----END PUBLIC KEY-----
Example (SealOpen) ¶
package main import ( "bytes" "crypto/elliptic" "crypto/rand" "fmt" "gitlab.com/elktree/ecc" ) func main() { // create keys, NB: different curves are used for sender and receiver sendersPub, sendersPriv, _ := ecc.GenerateKeys(elliptic.P224()) receiversPub, receiversPriv, _ := ecc.GenerateKeys(elliptic.P521()) // get random bytes as plaintext plaintextBytes := make([]byte, 8192) if n, err := rand.Reader.Read(plaintextBytes); n != 8192 || err != nil { panic("failed to read random bytes") } // seal both signs and encrypts sealed, _ := sendersPriv.Seal(plaintextBytes, receiversPub) // send the sealed bytes // open decrypts and verifies the senders signature opened, _ := receiversPriv.Open(sealed, sendersPub) compared := bytes.Compare(plaintextBytes, opened) fmt.Println(compared == 0) }
Output: true
Example (SignMessage) ¶
package main import ( "crypto/elliptic" "fmt" "gitlab.com/elktree/ecc" ) func main() { // create keys pub, priv, _ := ecc.GenerateKeys(elliptic.P384()) plaintext := "secret secrets are no fun, secret secrets hurt someone" // Sign the message with the senders private key. sig, _ := priv.SignMessage([]byte(plaintext)) // send plaintext and sig // Verify the signature with the senders public key. verified, _ := pub.VerifyMessage([]byte(plaintext), sig) fmt.Println(verified) }
Output: true
Example (SignVerify) ¶
package main import ( "crypto/elliptic" "crypto/rand" "crypto/sha256" "fmt" "gitlab.com/elktree/ecc" ) func main() { // create keys pub, priv, _ := ecc.GenerateKeys(elliptic.P224()) // get random bytes as plaintext plaintextBytes := make([]byte, 2500) if n, err := rand.Reader.Read(plaintextBytes); n != 2500 || err != nil { panic("failed to read random bytes") } hash := sha256.Sum256(plaintextBytes) // Sign the hash with the senders private key. sig, _ := priv.Sign(hash[:]) // hash is type [32]byte, need []byte // send plaintext and sig // Verify the signature with the senders public key. The recipient should // create the hash from the plaintext (here we reuse the hash). verified, _ := pub.Verify(hash[:], sig) fmt.Println(verified) }
Output: true
Index ¶
- func GenerateKeys(curve elliptic.Curve) (pub *PublicKey, priv *PrivateKey, err error)
- type PrivateKey
- func (priv *PrivateKey) Decrypt(encrypted []byte) (message []byte, err error)
- func (priv *PrivateKey) Marshal() ([]byte, error)
- func (priv *PrivateKey) Open(sealed []byte, from *PublicKey) ([]byte, error)
- func (priv *PrivateKey) PEM(password string) ([]byte, error)
- func (priv *PrivateKey) Seal(message []byte, to *PublicKey) (sealed []byte, err error)
- func (priv *PrivateKey) Sign(hash []byte) (signature []byte, err error)
- func (priv *PrivateKey) SignMessage(message []byte) (signature []byte, err error)
- type PublicKey
- func (pub *PublicKey) Encrypt(message []byte) (encrypted []byte, err error)
- func (pub *PublicKey) Marshal() []byte
- func (pub *PublicKey) PEM() ([]byte, error)
- func (pub *PublicKey) Verify(hash, signature []byte) (bool, error)
- func (pub *PublicKey) VerifyMessage(message, signature []byte) (verified bool, err error)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GenerateKeys ¶
func GenerateKeys(curve elliptic.Curve) (pub *PublicKey, priv *PrivateKey, err error)
GenerateKeys creates a new public and private key pair. Note that the public key is double the size of the private key. Using elliptic.P256() would make the private key 32 bytes and the public key 64 bytes.
pub, priv, err := ecc.GenerateKeys(elliptic.P256())
Types ¶
type PrivateKey ¶
type PrivateKey struct {
Key *ecdsa.PrivateKey
}
PrivateKey is the elliptic private key.
func DecodePEMPrivateKey ¶
func DecodePEMPrivateKey(pemEncodedKey []byte, password string) (*PrivateKey, error)
DecodePEMPrivateKey decodes the PEM format for the elliptic PrivateKey. If password is not blank, the PEM will be decrypted first.
pem.Decode will find the next PEM formatted block (certificate, private key etc) in the input. It returns that block and the remainder of the input. If no PEM data is found, p is nil and the whole of the input is returned in rest.
x509.DecryptPEMBlock takes a password encrypted PEM block and the password used to encrypt it and returns a slice of decrypted DER encoded bytes. It inspects the DEK-Info header to determine the algorithm used for decryption. If no DEK-Info header is present, an error is returned. If an incorrect password is detected an IncorrectPasswordError is returned. Because of deficiencies in the encrypted-PEM format, it's not always possible to detect an incorrect password. In these cases no error will be returned but the decrypted DER bytes will be random noise.
func UnmarshalPrivateKey ¶
func UnmarshalPrivateKey(marshalledKey []byte) (*PrivateKey, error)
UnmarshalPrivateKey loads a PrivateKey from a marshalled byte slice.
x509.ParseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
func (*PrivateKey) Decrypt ¶
func (priv *PrivateKey) Decrypt(encrypted []byte) (message []byte, err error)
Decrypt authenticates and recovers the original message from its input using the private key and the ephemeral key included in the message.
func (*PrivateKey) Marshal ¶
func (priv *PrivateKey) Marshal() ([]byte, error)
Marshal converts a PrivateKey to a byte slice.
MarshalECPrivateKey marshals an EC private key into ASN.1, DER format.
func (*PrivateKey) Open ¶
func (priv *PrivateKey) Open(sealed []byte, from *PublicKey) ([]byte, error)
Open decrypts and authenticates by calling Decrypt() and VerifyMessage(). Open is used after Seal().
func (*PrivateKey) PEM ¶
func (priv *PrivateKey) PEM(password string) ([]byte, error)
PEM marshals the PrivateKey and encodes it in standard PEM format. If password is not blank, the PEM will be encrypted using x509.PEMCipherAES256.
x509.MarshalECPrivateKey marshals an EC private key into ASN.1, DER format.
x509.EncryptPEMBlock returns a PEM block of the specified type holding the given DER-encoded data encrypted with the specified algorithm and password.
func (*PrivateKey) Seal ¶
func (priv *PrivateKey) Seal(message []byte, to *PublicKey) (sealed []byte, err error)
Seal authenticates and encrypts by calling SignMessage() and Encrypt(). Use Open() after Seal.
func (*PrivateKey) Sign ¶
func (priv *PrivateKey) Sign(hash []byte) (signature []byte, err error)
Sign uses the PrivateKey to create a signature of a hash (which should be the result of hashing a larger message.) Use Verify() after Sign.
If the hash is longer than the bit-length of the private key's curve order, the hash will be truncated to that length.
func (*PrivateKey) SignMessage ¶
func (priv *PrivateKey) SignMessage(message []byte) (signature []byte, err error)
SignMessage will hash the message with Sha256 and sign the hash. Returns a signature and error. Use VerifyMessage() after SignMessage.
type PublicKey ¶
PublicKey is the elliptic public key.
func DecodePEMPublicKey ¶
DecodePEMPublicKey decodes the PEM format for the elliptic PublicKey.
pem.Decode will find the next PEM formatted block (certificate, private key etc) in the input. It returns that block and the remainder of the input. If no PEM data is found, p is nil and the whole of the input is returned in rest.
func UnmarshalPublicKey ¶
UnmarshalPublicKey loads a PublicKey from a marshalled byte slice.
elliptic.Unmarshal converts a point, serialized by Marshal, into an x, y pair. It is an error if the point is not in uncompressed form or is not on the curve. On error, x = nil.
func (*PublicKey) Encrypt ¶
Encrypt secures and authenticates its input with the public key, using ECDHE with AES-128-CBC-HMAC-SHA1.
func (*PublicKey) Marshal ¶
Marshal converts the PublicKey to a byte slice.
elliptic.Marshal converts a point into the uncompressed form specified in section 4.3.6 of ANSI X9.62.
func (*PublicKey) PEM ¶
PEM marshals the PublicKey and encodes it in standard PEM format.
x509.MarshalPKIXPublicKey serialises a public key to DER-encoded PKIX format.
func (*PublicKey) Verify ¶
Verify checks the signature was created by the PrivateKey that goes with this PublicKey. Returns true if valid.
Signatures are created by the sender calling PrivateKey.Sign(hash) where the hash is of a larger message. The recipient uses the senders public key to check the senders signature. The recipient must hash the larger message (with the same algorithm) and verify the hash with the signature.
Directories ¶
Path | Synopsis |
---|---|
cmd
|
|
eccutil
Command eccutil is for working with elliptic curves.
|
Command eccutil is for working with elliptic curves. |
Package ecdh encrypts and decrypts data using elliptic curve keys.
|
Package ecdh encrypts and decrypts data using elliptic curve keys. |
libecc is a C wrapper for package ecc.
|
libecc is a C wrapper for package ecc. |
Package padding adds and removes padding for AES-CBC mode.
|
Package padding adds and removes padding for AES-CBC mode. |
Package symcrypt contains common symmetric encryption functions.
|
Package symcrypt contains common symmetric encryption functions. |