Skip to content

Instantly share code, notes, and snippets.

@valentinconan
Last active June 28, 2023 21:54
Show Gist options
  • Select an option

  • Save valentinconan/6dc46dd64483669b8ee621b58ba19e42 to your computer and use it in GitHub Desktop.

Select an option

Save valentinconan/6dc46dd64483669b8ee621b58ba19e42 to your computer and use it in GitHub Desktop.

Revisions

  1. valentinconan revised this gist Jun 28, 2023. No changes.
  2. valentinconan created this gist Jun 28, 2023.
    97 changes: 97 additions & 0 deletions EncodeSHA256WithDSA.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,97 @@
    package service

    import (
    "crypto/dsa"
    "crypto/rand"
    "crypto/sha256"
    "encoding/asn1"
    "encoding/base64"
    "encoding/pem"
    "errors"
    "log"
    "math/big"
    "os"
    )

    func encodeSHA256WithDSA() (string, error) {

    //read pem file from file system
    privateKeyData, err := os.ReadFile("./file.pem")
    if err != nil {
    log.Fatal(err)
    }

    hash, err := hash("dataToEncode")
    if err != nil {
    log.Fatal("hash:", err)
    }

    out, err := sign(hash, privateKeyData)

    return base64.StdEncoding.EncodeToString(out), nil
    }

    func hash(file []byte) ([]byte, error) {
    sum := sha256.Sum256(file)
    return sum[:], nil
    }

    func sign(hash []byte, file []byte) ([]byte, error) {

    block, _ := pem.Decode(file)
    if block == nil {
    return nil, errors.New("Failed to parse private key PEM")
    }

    priv, error := ParseDSAPrivateKey(block.Bytes)
    if error != nil {
    return nil, error
    }

    var s dsaSignature
    s.R, s.S, error = dsa.Sign(rand.Reader, priv, hash)
    if error != nil {
    return nil, error
    }

    return asn1.Marshal(s)
    }

    func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
    var k struct {
    Version int
    P *big.Int
    Q *big.Int
    G *big.Int
    Pub *big.Int
    Priv *big.Int
    }
    rest, err := asn1.Unmarshal(der, &k)
    if err != nil {
    return nil, errors.New("failed to parse DSA key: " + err.Error())
    }
    if len(rest) > 0 {
    return nil, errors.New("garbage after DSA key")
    }

    return &dsa.PrivateKey{
    PublicKey: dsa.PublicKey{
    Parameters: dsa.Parameters{
    P: k.P,
    Q: k.Q,
    G: k.G,
    },
    Y: k.Pub,
    },
    X: k.Priv,
    }, nil
    }

    type dsaPrivateKey struct {
    Version int
    P, Q, G, Y, X *big.Int
    }

    type dsaSignature struct {
    R, S *big.Int
    }