package jwtvalidation

import (
	"bytes"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"io"
)

// CalculatePubkeyFingerprint calculates an RSA public key's fingerprint
func CalculatePubkeyFingerprint(key io.Reader) (fingerprint string, err error) {
	const hashAlg = "SHA256:"

	h := sha256.New()
	_, err = io.Copy(h, key)
	if err != nil {
		return
	}

	rawFingerprint := h.Sum(nil)

	fingerprintBytes := make([]byte, 44+len(hashAlg))
	for nByte, c := range hashAlg {
		fingerprintBytes[nByte] = byte(c)
	}
	base64.StdEncoding.Encode(fingerprintBytes[len(hashAlg):], rawFingerprint)

	fingerprint = string(fingerprintBytes)
	return
}

// CalculatePubkeyFingerprintFromPrivateKey calculates the public key's
// fingerprint given a private key
func CalculatePubkeyFingerprintFromPrivateKey(key *rsa.PrivateKey) (fingerprint string, err error) {
	var pubBuf bytes.Buffer
	pubkeyDer, err := x509.MarshalPKIXPublicKey(key.Public())
	if err != nil {
		return
	}

	err = pem.Encode(&pubBuf, &pem.Block{
		Type:  "RSA PUBLIC KEY",
		Bytes: pubkeyDer,
	})
	if err != nil {
		return
	}

	fingerprint, err = CalculatePubkeyFingerprint(&pubBuf)
	return
}
