Skip to content

Instantly share code, notes, and snippets.

@valentinconan
Last active June 28, 2023 21:54
Show Gist options
  • Save valentinconan/6dc46dd64483669b8ee621b58ba19e42 to your computer and use it in GitHub Desktop.
Save valentinconan/6dc46dd64483669b8ee621b58ba19e42 to your computer and use it in GitHub Desktop.
Signature using SHA256 with DSA and a PEM file as private key
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
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment