tSeparate RSA functions into a separate file. - tordam - A library for peer discovery inside the Tor network
 (HTM) git clone https://git.parazyd.org/tordam
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit e2de1893f1c13c07b2394820fd224e1f58655a0f
 (DIR) parent 1af7f5d90c331d73e3c82dfe51d551e63aba05be
 (HTM) Author: parazyd <parazyd@dyne.org>
       Date:   Tue, 12 Dec 2017 22:17:34 +0100
       
       Separate RSA functions into a separate file.
       
       This commit is a future plan, when we will support Tor v3 Hidden
       Services usind ed25519.
       
       Diffstat:
         D pkg/damlib/crypto.go                |     219 -------------------------------
         A pkg/damlib/crypto_common.go         |      26 ++++++++++++++++++++++++++
         A pkg/damlib/crypto_rsa.go            |     198 +++++++++++++++++++++++++++++++
       
       3 files changed, 224 insertions(+), 219 deletions(-)
       ---
 (DIR) diff --git a/pkg/damlib/crypto.go b/pkg/damlib/crypto.go
       t@@ -1,219 +0,0 @@
       -package damlib
       -
       -// See LICENSE file for copyright and license details.
       -
       -import (
       -        "crypto"
       -        "crypto/rand"
       -        "crypto/rsa"
       -        "crypto/sha1"
       -        "crypto/sha512"
       -        "crypto/x509"
       -        "encoding/asn1"
       -        "encoding/base32"
       -        "encoding/pem"
       -        "errors"
       -        "io/ioutil"
       -        "log"
       -        "math/big"
       -        "os"
       -        "strings"
       -)
       -
       -// GenRsa generates a private RSA keypair of a given bitSize int and returns it
       -// as rsa.PrivateKey.
       -func GenRsa(bitSize int) (*rsa.PrivateKey, error) {
       -        log.Printf("Generating %d-bit RSA keypair...\n", bitSize)
       -        rng := rand.Reader
       -        key, err := rsa.GenerateKey(rng, bitSize)
       -        if err != nil {
       -                return nil, err
       -        }
       -        return key, nil
       -}
       -
       -// SavePubRsa saves a given RSA public key to a given filename.
       -// SavePubRsa takes the filename to write as a string, and the key as
       -// rsa.PublicKey. It returns a boolean value and an error, depending on whether
       -// it has failed or not.
       -func SavePubRsa(filename string, pubkey rsa.PublicKey) (bool, error) {
       -        log.Printf("Writing pubkey to %s\n", filename)
       -        // FIXME: worry or not about creating the path if it doesn't exist?
       -        outfile, err := os.Create(filename)
       -        defer outfile.Close()
       -        if err != nil {
       -                return false, err
       -        }
       -        asn1Bytes, err := asn1.Marshal(pubkey)
       -        if err != nil {
       -                return false, err
       -        }
       -        var pemkey = &pem.Block{
       -                Type:  "RSA PUBLIC KEY",
       -                Bytes: asn1Bytes,
       -        }
       -        err = pem.Encode(outfile, pemkey)
       -        if err != nil {
       -                return false, err
       -        }
       -        err = outfile.Chmod(0400)
       -        if err != nil {
       -                return false, err
       -        }
       -        return true, nil
       -}
       -
       -// SavePrivRsa saves a given RSA private key to a given filename.
       -// SavePrivRsa takes the filename to write as a string, and the key as
       -// *rsa.PrivateKey. It returns a boolean value and an error, depending on whether
       -// it has failed or not.
       -func SavePrivRsa(filename string, privkey *rsa.PrivateKey) (bool, error) {
       -        log.Printf("Writing private key to %s\n", filename)
       -        // FIXME: worry or not about creating the path if it doesn't exist?
       -        outfile, err := os.Create(filename)
       -        defer outfile.Close()
       -        if err != nil {
       -                return false, err
       -        }
       -        var pemkey = &pem.Block{
       -                Type:  "RSA PRIVATE KEY",
       -                Bytes: x509.MarshalPKCS1PrivateKey(privkey),
       -        }
       -        err = pem.Encode(outfile, pemkey)
       -        if err != nil {
       -                return false, err
       -        }
       -        err = outfile.Chmod(0400)
       -        if err != nil {
       -                return false, err
       -        }
       -        return true, nil
       -}
       -
       -// LoadRsaKeyFromFile loads a RSA private key from a given filename.
       -// LoadRsaKeyFromFile takes a string filename and tries to read from it, parsing
       -// the private RSA key. It will return a *rsa.PrivateKey on success, and error
       -// on fail.
       -func LoadRsaKeyFromFile(filename string) (*rsa.PrivateKey, error) {
       -        log.Println("Loading RSA private key from", filename)
       -        dat, err := ioutil.ReadFile(filename)
       -        if err != nil {
       -                return nil, err
       -        }
       -        block, _ := pem.Decode(dat)
       -        if block == nil {
       -                return nil, errors.New("failed to parse PEM block containing the key")
       -        }
       -        priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
       -        if err != nil {
       -                return nil, err
       -        }
       -        return priv, nil
       -}
       -
       -// SignMsgRsa signs a given []byte message using a given RSA private key.
       -// It will return the signature as a slice of bytes on success, and error on
       -// failure.
       -func SignMsgRsa(message []byte, privkey *rsa.PrivateKey) ([]byte, error) {
       -        log.Println("Signing message...")
       -        rng := rand.Reader
       -        hashed := sha512.Sum512(message)
       -        sig, err := rsa.SignPKCS1v15(rng, privkey, crypto.SHA512, hashed[:])
       -        if err != nil {
       -                return nil, err
       -        }
       -        return sig, nil
       -}
       -
       -// EncryptMsgRsa encrypts a given []byte message using a given RSA public key.
       -// Returns the encrypted message as a slice of bytes on success, and error on
       -// failure.
       -func EncryptMsgRsa(message []byte, pubkey *rsa.PublicKey) ([]byte, error) {
       -        log.Println("Encrypting message...")
       -        rng := rand.Reader
       -        msg, err := rsa.EncryptPKCS1v15(rng, pubkey, message)
       -        if err != nil {
       -                return nil, err
       -        }
       -        return msg, nil
       -}
       -
       -// DecryptMsgRsa decrypts a given []byte message using a given RSA private key.
       -// Returns the decrypted message as a slice of bytes on success, and error on
       -// failure.
       -func DecryptMsgRsa(message []byte, privkey *rsa.PrivateKey) ([]byte, error) {
       -        log.Println("Decrypting message...")
       -        rng := rand.Reader
       -        msg, err := rsa.DecryptPKCS1v15(rng, privkey, message)
       -        if err != nil {
       -                return nil, err
       -        }
       -        return msg, nil
       -}
       -
       -// VerifyMsgRsa verifies a message and signature against a given RSA pubkey.
       -// Returns a boolean value and error depending on whether it has failed or not.
       -func VerifyMsgRsa(message []byte, signature []byte, pubkey *rsa.PublicKey) (bool, error) {
       -        log.Println("Verifying message signature")
       -        hashed := sha512.Sum512(message)
       -        err := rsa.VerifyPKCS1v15(pubkey, crypto.SHA512, hashed[:], signature)
       -        if err != nil {
       -                log.Println("Signature invalid")
       -                return false, err
       -        }
       -        log.Println("Signature valid")
       -        return true, nil
       -}
       -
       -// OnionFromPubkeyRsa generates a valid onion address from a given RSA pubkey.
       -// Returns the onion address as a slice of bytes on success and error on
       -// failure.
       -func OnionFromPubkeyRsa(pubkey rsa.PublicKey) ([]byte, error) {
       -        asn1Bytes, err := asn1.Marshal(pubkey)
       -        if err != nil {
       -                return nil, err
       -        }
       -        hashed := sha1.New()
       -        _, err = hashed.Write(asn1Bytes)
       -        if err != nil {
       -                return nil, err
       -        }
       -        encoded := strings.ToLower(base32.StdEncoding.EncodeToString(hashed.Sum(nil)))[:16]
       -        encoded += ".onion"
       -
       -        return []byte(encoded), nil
       -}
       -
       -// ParsePubkeyRsa parses a []byte form of a RSA public key and returns it as
       -// *rsa.PublicKey on success. Otherwise, error.
       -func ParsePubkeyRsa(pubkey []byte) (*rsa.PublicKey, error) {
       -        var pub rsa.PublicKey
       -        var ret *rsa.PublicKey
       -        block, _ := pem.Decode(pubkey)
       -        _, err := asn1.Unmarshal(block.Bytes, &pub)
       -        if err != nil {
       -                return nil, err
       -        }
       -        ret = &pub
       -        return ret, nil
       -}
       -
       -// GenRandomASCII generates a random ASCII string of a given length.
       -// Takes length int as argument, and returns a string of that length on success
       -// and error on failure.
       -func GenRandomASCII(length int) (string, error) {
       -        var res string
       -        for {
       -                if len(res) >= length {
       -                        return res, nil
       -                }
       -                num, err := rand.Int(rand.Reader, big.NewInt(int64(127)))
       -                if err != nil {
       -                        return "", err
       -                }
       -                n := num.Int64()
       -                if n > 32 && n < 127 {
       -                        res += string(n)
       -                }
       -        }
       -}
 (DIR) diff --git a/pkg/damlib/crypto_common.go b/pkg/damlib/crypto_common.go
       t@@ -0,0 +1,26 @@
       +package damlib
       +
       +import (
       +        "crypto/rand"
       +        "math/big"
       +)
       +
       +// GenRandomASCII generates a random ASCII string of a given length.
       +// Takes length int as argument, and returns a string of that length on success
       +// and error on failure.
       +func GenRandomASCII(length int) (string, error) {
       +        var res string
       +        for {
       +                if len(res) >= length {
       +                        return res, nil
       +                }
       +                num, err := rand.Int(rand.Reader, big.NewInt(int64(127)))
       +                if err != nil {
       +                        return "", err
       +                }
       +                n := num.Int64()
       +                if n > 32 && n < 127 {
       +                        res += string(n)
       +                }
       +        }
       +}
 (DIR) diff --git a/pkg/damlib/crypto_rsa.go b/pkg/damlib/crypto_rsa.go
       t@@ -0,0 +1,198 @@
       +package damlib
       +
       +// See LICENSE file for copyright and license details.
       +
       +import (
       +        "crypto"
       +        "crypto/rand"
       +        "crypto/rsa"
       +        "crypto/sha1"
       +        "crypto/sha512"
       +        "crypto/x509"
       +        "encoding/asn1"
       +        "encoding/base32"
       +        "encoding/pem"
       +        "errors"
       +        "io/ioutil"
       +        "log"
       +        "os"
       +        "strings"
       +)
       +
       +// GenRsa generates a private RSA keypair of a given bitSize int and returns it
       +// as rsa.PrivateKey.
       +func GenRsa(bitSize int) (*rsa.PrivateKey, error) {
       +        log.Printf("Generating %d-bit RSA keypair...\n", bitSize)
       +        rng := rand.Reader
       +        key, err := rsa.GenerateKey(rng, bitSize)
       +        if err != nil {
       +                return nil, err
       +        }
       +        return key, nil
       +}
       +
       +// SavePubRsa saves a given RSA public key to a given filename.
       +// SavePubRsa takes the filename to write as a string, and the key as
       +// rsa.PublicKey. It returns a boolean value and an error, depending on whether
       +// it has failed or not.
       +func SavePubRsa(filename string, pubkey rsa.PublicKey) (bool, error) {
       +        log.Printf("Writing pubkey to %s\n", filename)
       +        // FIXME: worry or not about creating the path if it doesn't exist?
       +        outfile, err := os.Create(filename)
       +        defer outfile.Close()
       +        if err != nil {
       +                return false, err
       +        }
       +        asn1Bytes, err := asn1.Marshal(pubkey)
       +        if err != nil {
       +                return false, err
       +        }
       +        var pemkey = &pem.Block{
       +                Type:  "RSA PUBLIC KEY",
       +                Bytes: asn1Bytes,
       +        }
       +        err = pem.Encode(outfile, pemkey)
       +        if err != nil {
       +                return false, err
       +        }
       +        err = outfile.Chmod(0400)
       +        if err != nil {
       +                return false, err
       +        }
       +        return true, nil
       +}
       +
       +// SavePrivRsa saves a given RSA private key to a given filename.
       +// SavePrivRsa takes the filename to write as a string, and the key as
       +// *rsa.PrivateKey. It returns a boolean value and an error, depending on whether
       +// it has failed or not.
       +func SavePrivRsa(filename string, privkey *rsa.PrivateKey) (bool, error) {
       +        log.Printf("Writing private key to %s\n", filename)
       +        // FIXME: worry or not about creating the path if it doesn't exist?
       +        outfile, err := os.Create(filename)
       +        defer outfile.Close()
       +        if err != nil {
       +                return false, err
       +        }
       +        var pemkey = &pem.Block{
       +                Type:  "RSA PRIVATE KEY",
       +                Bytes: x509.MarshalPKCS1PrivateKey(privkey),
       +        }
       +        err = pem.Encode(outfile, pemkey)
       +        if err != nil {
       +                return false, err
       +        }
       +        err = outfile.Chmod(0400)
       +        if err != nil {
       +                return false, err
       +        }
       +        return true, nil
       +}
       +
       +// LoadRsaKeyFromFile loads a RSA private key from a given filename.
       +// LoadRsaKeyFromFile takes a string filename and tries to read from it, parsing
       +// the private RSA key. It will return a *rsa.PrivateKey on success, and error
       +// on fail.
       +func LoadRsaKeyFromFile(filename string) (*rsa.PrivateKey, error) {
       +        log.Println("Loading RSA private key from", filename)
       +        dat, err := ioutil.ReadFile(filename)
       +        if err != nil {
       +                return nil, err
       +        }
       +        block, _ := pem.Decode(dat)
       +        if block == nil {
       +                return nil, errors.New("failed to parse PEM block containing the key")
       +        }
       +        priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
       +        if err != nil {
       +                return nil, err
       +        }
       +        return priv, nil
       +}
       +
       +// SignMsgRsa signs a given []byte message using a given RSA private key.
       +// It will return the signature as a slice of bytes on success, and error on
       +// failure.
       +func SignMsgRsa(message []byte, privkey *rsa.PrivateKey) ([]byte, error) {
       +        log.Println("Signing message...")
       +        rng := rand.Reader
       +        hashed := sha512.Sum512(message)
       +        sig, err := rsa.SignPKCS1v15(rng, privkey, crypto.SHA512, hashed[:])
       +        if err != nil {
       +                return nil, err
       +        }
       +        return sig, nil
       +}
       +
       +// EncryptMsgRsa encrypts a given []byte message using a given RSA public key.
       +// Returns the encrypted message as a slice of bytes on success, and error on
       +// failure.
       +func EncryptMsgRsa(message []byte, pubkey *rsa.PublicKey) ([]byte, error) {
       +        log.Println("Encrypting message...")
       +        rng := rand.Reader
       +        msg, err := rsa.EncryptPKCS1v15(rng, pubkey, message)
       +        if err != nil {
       +                return nil, err
       +        }
       +        return msg, nil
       +}
       +
       +// DecryptMsgRsa decrypts a given []byte message using a given RSA private key.
       +// Returns the decrypted message as a slice of bytes on success, and error on
       +// failure.
       +func DecryptMsgRsa(message []byte, privkey *rsa.PrivateKey) ([]byte, error) {
       +        log.Println("Decrypting message...")
       +        rng := rand.Reader
       +        msg, err := rsa.DecryptPKCS1v15(rng, privkey, message)
       +        if err != nil {
       +                return nil, err
       +        }
       +        return msg, nil
       +}
       +
       +// VerifyMsgRsa verifies a message and signature against a given RSA pubkey.
       +// Returns a boolean value and error depending on whether it has failed or not.
       +func VerifyMsgRsa(message []byte, signature []byte, pubkey *rsa.PublicKey) (bool, error) {
       +        log.Println("Verifying message signature")
       +        hashed := sha512.Sum512(message)
       +        err := rsa.VerifyPKCS1v15(pubkey, crypto.SHA512, hashed[:], signature)
       +        if err != nil {
       +                log.Println("Signature invalid")
       +                return false, err
       +        }
       +        log.Println("Signature valid")
       +        return true, nil
       +}
       +
       +// OnionFromPubkeyRsa generates a valid onion address from a given RSA pubkey.
       +// Returns the onion address as a slice of bytes on success and error on
       +// failure.
       +func OnionFromPubkeyRsa(pubkey rsa.PublicKey) ([]byte, error) {
       +        asn1Bytes, err := asn1.Marshal(pubkey)
       +        if err != nil {
       +                return nil, err
       +        }
       +        hashed := sha1.New()
       +        _, err = hashed.Write(asn1Bytes)
       +        if err != nil {
       +                return nil, err
       +        }
       +        encoded := strings.ToLower(base32.StdEncoding.EncodeToString(hashed.Sum(nil)))[:16]
       +        encoded += ".onion"
       +
       +        return []byte(encoded), nil
       +}
       +
       +// ParsePubkeyRsa parses a []byte form of a RSA public key and returns it as
       +// *rsa.PublicKey on success. Otherwise, error.
       +func ParsePubkeyRsa(pubkey []byte) (*rsa.PublicKey, error) {
       +        var pub rsa.PublicKey
       +        var ret *rsa.PublicKey
       +        block, _ := pem.Decode(pubkey)
       +        _, err := asn1.Unmarshal(block.Bytes, &pub)
       +        if err != nil {
       +                return nil, err
       +        }
       +        ret = &pub
       +        return ret, nil
       +}