auth/algo/rs/rs.go
shchva fd8edfb70a create: pkg algo/rs
pkg algo/rs подписывает данные с помощью ключа RSA
2025-01-10 18:35:11 +03:00

120 lines
2.0 KiB
Go

package rs
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"io"
"git.daebt.dev/auth/algo"
)
const (
KeyRSA algo.KeyType = "RSA"
AlgorithmRS256 algo.AlgorithmType = "RS256"
AlgorithmRS384 algo.AlgorithmType = "RS384"
AlgorithmRS512 algo.AlgorithmType = "RS512"
)
type Algo struct {
k algo.KeyType
a algo.AlgorithmType
h crypto.Hash
p *rsa.PrivateKey
}
func (a *Algo) Sign(payload []byte) ([]byte, error) {
val, err := a.hasher(payload)
if err != nil {
return nil, err
}
return rsa.SignPKCS1v15(rand.Reader, a.p, a.h, val)
}
func (a *Algo) Verify(payload, signature []byte) error {
val, err := a.hasher(payload)
if err != nil {
return err
}
if rsa.VerifyPKCS1v15(&a.p.PublicKey, a.h, val, signature) != nil {
return algo.ErrInvalidSignature
}
return nil
}
func (a *Algo) Key() algo.KeyType {
return a.k
}
func (a *Algo) Algo() algo.AlgorithmType {
return a.a
}
func (a *Algo) hasher(payload []byte) ([]byte, error) {
val := a.h.New()
if _, err := val.Write(payload); err != nil {
return nil, err
}
return val.Sum(nil), nil
}
func (a *Algo) WriteKeyPEM(w io.Writer) error {
return pem.Encode(w, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(a.p),
})
}
func (a *Algo) WritePubPEM(w io.Writer) error {
return pem.Encode(w, &pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: x509.MarshalPKCS1PublicKey(&a.p.PublicKey),
})
}
func newRS(a *Algo, o ...Option) (*Algo, error) {
for _, f := range o {
if err := f(a); err != nil {
return nil, err
}
}
if a.p == nil {
return nil, errors.New("key is not initialized")
}
return a, nil
}
func NewRS256(o ...Option) (*Algo, error) {
return newRS(&Algo{
k: KeyRSA,
a: AlgorithmRS256,
h: crypto.SHA256,
}, o...)
}
func NewRS384(o ...Option) (*Algo, error) {
return newRS(&Algo{
k: KeyRSA,
a: AlgorithmRS384,
h: crypto.SHA384,
}, o...)
}
func NewRS512(o ...Option) (*Algo, error) {
return newRS(&Algo{
k: KeyRSA,
a: AlgorithmRS512,
h: crypto.SHA512,
}, o...)
}