Files
did-it/crypto/rsa/public.go
Michael Muré 538ea436ca WIP RSA support
2025-07-08 12:57:49 +02:00

135 lines
3.2 KiB
Go

package rsa
import (
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"math/big"
"github.com/INFURA/go-did/crypto"
helpers "github.com/INFURA/go-did/crypto/internal"
)
var _ crypto.PublicKeySigning = &PublicKey{}
type PublicKey struct {
k *rsa.PublicKey
}
func PublicKeyFromPKCS1DER(bytes []byte) (*PublicKey, error) {
pub, err := x509.ParsePKCS1PublicKey(bytes)
if err != nil {
return nil, err
}
return &PublicKey{k: pub}, nil
}
func PublicKeyFromNE(n, e []byte) (*PublicKey, error) {
nBInt := new(big.Int).SetBytes(n)
// some basic checks
if nBInt.Sign() <= 0 {
return nil, fmt.Errorf("invalid modulus")
}
if nBInt.BitLen() < MinRsaKeyBits {
return nil, fmt.Errorf("key length too small")
}
if nBInt.BitLen() > MaxRsaKeyBits {
return nil, fmt.Errorf("key length too large")
}
if nBInt.Bit(0) == 0 {
return nil, fmt.Errorf("modulus must be odd")
}
eBInt := new(big.Int).SetBytes(e)
// some basic checks
if !eBInt.IsInt64() {
return nil, fmt.Errorf("invalid exponent")
}
if eBInt.Sign() <= 0 {
return nil, fmt.Errorf("exponent must be positive")
}
if eBInt.Bit(0) == 0 {
return nil, fmt.Errorf("exponent must be odd")
}
return &PublicKey{k: &rsa.PublicKey{N: nBInt, E: int(eBInt.Int64())}}, nil
}
// PublicKeyFromPublicKeyMultibase decodes the public key from its Multibase form
func PublicKeyFromPublicKeyMultibase(multibase string) (*PublicKey, error) {
code, bytes, err := helpers.PublicKeyMultibaseDecode(multibase)
if err != nil {
return nil, err
}
if code != MultibaseCode {
return nil, fmt.Errorf("invalid code")
}
return PublicKeyFromX509DER(bytes)
}
// PublicKeyFromX509DER decodes an X.509 DER (binary) encoded public key.
func PublicKeyFromX509DER(bytes []byte) (*PublicKey, error) {
pub, err := x509.ParsePKIXPublicKey(bytes)
if err != nil {
return nil, err
}
return &PublicKey{k: pub.(*rsa.PublicKey)}, nil
}
// PublicKeyFromX509PEM decodes an X.509 PEM (string) encoded public key.
func PublicKeyFromX509PEM(str string) (*PublicKey, error) {
block, _ := pem.Decode([]byte(str))
if block == nil {
return nil, fmt.Errorf("failed to decode PEM block")
}
if block.Type != pemPubBlockType {
return nil, fmt.Errorf("incorrect PEM block type")
}
return PublicKeyFromX509DER(block.Bytes)
}
func (p *PublicKey) BitLen() int {
return p.k.N.BitLen()
}
func (p *PublicKey) NBytes() []byte {
return p.k.N.Bytes()
}
func (p *PublicKey) EBytes() []byte {
return new(big.Int).SetInt64(int64(p.k.E)).Bytes()
}
func (p *PublicKey) Equal(other crypto.PublicKey) bool {
if other, ok := other.(*PublicKey); ok {
return p.k.Equal(other.k)
}
return false
}
func (p *PublicKey) ToPublicKeyMultibase() string {
bytes := p.ToX509DER()
return helpers.PublicKeyMultibaseEncode(MultibaseCode, bytes)
}
func (p *PublicKey) ToX509DER() []byte {
res, _ := x509.MarshalPKIXPublicKey(p.k)
return res
}
func (p *PublicKey) ToX509PEM() string {
der := p.ToX509DER()
return string(pem.EncodeToMemory(&pem.Block{
Type: pemPubBlockType,
Bytes: der,
}))
}
func (p *PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.SigningOption) bool {
return false
}
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
return false
}