2022-02-26 12:44:43 +00:00
|
|
|
package crypto
|
|
|
|
|
|
|
|
import (
|
2024-01-04 06:26:03 +00:00
|
|
|
"crypto/sha256"
|
2022-02-26 12:44:43 +00:00
|
|
|
"crypto/x509"
|
2024-01-04 06:26:03 +00:00
|
|
|
"encoding/hex"
|
2022-02-28 15:56:49 +00:00
|
|
|
"encoding/json"
|
2022-02-26 12:44:43 +00:00
|
|
|
|
2022-02-26 15:06:22 +00:00
|
|
|
"github.com/authorizerdev/authorizer/server/constants"
|
2022-05-29 11:52:46 +00:00
|
|
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
2022-02-28 15:56:49 +00:00
|
|
|
"golang.org/x/crypto/bcrypt"
|
2022-02-26 12:44:43 +00:00
|
|
|
"gopkg.in/square/go-jose.v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
// GetPubJWK returns JWK for given keys
|
|
|
|
func GetPubJWK(algo, keyID string, publicKey interface{}) (string, error) {
|
|
|
|
jwk := &jose.JSONWebKeySet{
|
|
|
|
Keys: []jose.JSONWebKey{
|
|
|
|
{
|
|
|
|
Algorithm: algo,
|
|
|
|
Key: publicKey,
|
|
|
|
Use: "sig",
|
|
|
|
KeyID: keyID,
|
|
|
|
Certificates: []*x509.Certificate{},
|
|
|
|
CertificateThumbprintSHA1: []uint8{},
|
|
|
|
CertificateThumbprintSHA256: []uint8{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
jwkPublicKey, err := jwk.Keys[0].MarshalJSON()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return string(jwkPublicKey), nil
|
|
|
|
}
|
2022-02-26 15:06:22 +00:00
|
|
|
|
|
|
|
// GenerateJWKBasedOnEnv generates JWK based on env
|
2022-02-28 02:25:01 +00:00
|
|
|
// make sure clientID, jwtType, jwtSecret / public & private key pair is set
|
|
|
|
// this is called while initializing app / when env is updated
|
2022-02-26 15:06:22 +00:00
|
|
|
func GenerateJWKBasedOnEnv() (string, error) {
|
|
|
|
jwk := ""
|
2022-05-29 11:52:46 +00:00
|
|
|
algo, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
|
|
|
if err != nil {
|
|
|
|
return jwk, err
|
|
|
|
}
|
|
|
|
clientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyClientID)
|
|
|
|
if err != nil {
|
|
|
|
return jwk, err
|
|
|
|
}
|
|
|
|
|
|
|
|
jwtSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)
|
|
|
|
if err != nil {
|
|
|
|
return jwk, err
|
|
|
|
}
|
2022-02-26 15:06:22 +00:00
|
|
|
|
|
|
|
// check if jwt secret is provided
|
|
|
|
if IsHMACA(algo) {
|
2022-05-29 11:52:46 +00:00
|
|
|
jwk, err = GetPubJWK(algo, clientID, []byte(jwtSecret))
|
2022-02-26 15:06:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-29 11:52:46 +00:00
|
|
|
jwtPublicKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
|
|
|
|
if err != nil {
|
|
|
|
return jwk, err
|
|
|
|
}
|
|
|
|
|
2022-02-26 15:06:22 +00:00
|
|
|
if IsRSA(algo) {
|
2022-05-29 11:52:46 +00:00
|
|
|
publicKeyInstance, err := ParseRsaPublicKeyFromPemStr(jwtPublicKey)
|
2022-02-26 15:06:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
jwk, err = GetPubJWK(algo, clientID, publicKeyInstance)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if IsECDSA(algo) {
|
2022-05-29 11:52:46 +00:00
|
|
|
jwtPublicKey, err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
|
|
|
|
if err != nil {
|
|
|
|
return jwk, err
|
|
|
|
}
|
|
|
|
publicKeyInstance, err := ParseEcdsaPublicKeyFromPemStr(jwtPublicKey)
|
2022-02-26 15:06:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
jwk, err = GetPubJWK(algo, clientID, publicKeyInstance)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return jwk, nil
|
|
|
|
}
|
2022-02-28 15:56:49 +00:00
|
|
|
|
|
|
|
// EncryptEnvData is used to encrypt the env data
|
2022-05-29 11:52:46 +00:00
|
|
|
func EncryptEnvData(data map[string]interface{}) (string, error) {
|
2022-02-28 15:56:49 +00:00
|
|
|
jsonBytes, err := json.Marshal(data)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2022-05-29 11:52:46 +00:00
|
|
|
storeData, err := memorystore.Provider.GetEnvStore()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2022-02-28 15:56:49 +00:00
|
|
|
|
|
|
|
err = json.Unmarshal(jsonBytes, &storeData)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
configData, err := json.Marshal(storeData)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2022-03-07 13:19:18 +00:00
|
|
|
|
2022-03-07 09:59:37 +00:00
|
|
|
encryptedConfig, err := EncryptAESEnv(configData)
|
2022-02-28 15:56:49 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2022-03-07 10:46:54 +00:00
|
|
|
return EncryptB64(string(encryptedConfig)), nil
|
2022-02-28 15:56:49 +00:00
|
|
|
}
|
|
|
|
|
2024-01-04 06:26:03 +00:00
|
|
|
// getSHA256 calculates the SHA-256 hash of a string
|
|
|
|
func getSHA256(input string) string {
|
|
|
|
hash := sha256.New()
|
|
|
|
hash.Write([]byte(input))
|
|
|
|
return hex.EncodeToString(hash.Sum(nil))
|
|
|
|
}
|
|
|
|
|
|
|
|
// VerifyPassword compares a stored hashed password with a user-provided password
|
|
|
|
func VerifyPassword(storedHashedPassword, userProvidedPassword string) error {
|
|
|
|
passwordSHA256 := getSHA256(userProvidedPassword)
|
|
|
|
// CompareHashAndPassword returns nil on success
|
|
|
|
err := bcrypt.CompareHashAndPassword([]byte(storedHashedPassword), []byte(passwordSHA256))
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-02-28 15:56:49 +00:00
|
|
|
// EncryptPassword is used for encrypting password
|
|
|
|
func EncryptPassword(password string) (string, error) {
|
2024-01-04 18:38:53 +00:00
|
|
|
pw, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
2022-02-28 15:56:49 +00:00
|
|
|
if err != nil {
|
2024-01-04 18:38:53 +00:00
|
|
|
password = getSHA256(password)
|
|
|
|
pw, err = bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2022-02-28 15:56:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return string(pw), nil
|
|
|
|
}
|