Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPKeyStore #74

Open
avi94 opened this issue Sep 15, 2020 · 3 comments
Open

SPKeyStore #74

avi94 opened this issue Sep 15, 2020 · 3 comments

Comments

@avi94
Copy link

avi94 commented Sep 15, 2020

Is there any actual examples of SPKeyStore being set to a valid keystore? It's really confusing how to make this field consume some sort of keystore, preferably a JKS file.

@konaraya
Copy link

konaraya commented Sep 16, 2020

TestSAML has an example on how to use SPKeyStore.
Check TLSCertKeyStore from goxmldsig on how to use a crypto/tls certificate with it.
To use a JKS file you would need to convert it to a tls.Certificate and use it.

@shaozi
Copy link

shaozi commented Nov 8, 2023

I am still confused on how to set the SPKeyStore. Do I need to create my own KeyStore type that conforms with X509KeyStore interface?

@viotile
Copy link

viotile commented Dec 5, 2024

How to Set Up an Interface for Handling Key Stores

Below is a complete example demonstrating how to set up an interface to manage private keys and certificates.

1. Define the Key Store Struct
Create a LocalKeyStore struct to hold the file paths for the private key and certificate.

type LocalKeyStore struct {
	privateKeyPath  string
	certificatePath string
}

func NewLocalKeyStore(privateKeyPath, certificatePath string) dsig.X509KeyStore {
	return &LocalKeyStore{
		privateKeyPath:  privateKeyPath,
		certificatePath: certificatePath,
	}
}

2. Implement the GetKeyPair Method
This method reads the private key and certificate from the provided file paths, decodes them, and parses the respective content.

func (s *LocalKeyStore) GetKeyPair() (*rsa.PrivateKey, []byte, error) {
	// Read the private key file
	privateKeyBytes, err := os.ReadFile(s.privateKeyPath)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to read private key file: %w", err)
	}

	// Decode the PEM block
	block, _ := pem.Decode(privateKeyBytes)
	if block == nil || (block.Type != "PRIVATE KEY" && block.Type != "RSA PRIVATE KEY") {
		return nil, nil, fmt.Errorf("invalid PEM block for private key (type: %v)", block.Type)
	}

	// Parse the private key
	var privateKey *rsa.PrivateKey
	if block.Type == "RSA PRIVATE KEY" {
		// PKCS#1 format
		privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
		if err != nil {
			return nil, nil, fmt.Errorf("failed to parse PKCS#1 private key: %w", err)
		}
	} else if block.Type == "PRIVATE KEY" {
		// PKCS#8 format
		parsedKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
		if err != nil {
			return nil, nil, fmt.Errorf("failed to parse PKCS#8 private key: %w", err)
		}
		// Ensure the parsed key is of type RSA
		var ok bool
		privateKey, ok = parsedKey.(*rsa.PrivateKey)
		if !ok {
			return nil, nil, fmt.Errorf("parsed private key is not an RSA key")
		}
	}

	// Read the certificate file
	certBytes, err := os.ReadFile(s.certificatePath)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to read certificate file: %w", err)
	}

	// Decode the PEM block for the certificate
	block, _ = pem.Decode(certBytes)
	if block == nil || block.Type != "CERTIFICATE" {
		return nil, nil, fmt.Errorf("invalid PEM block for certificate (type: %v)", block.Type)
	}

	// Parse the certificate
	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to parse certificate: %w", err)
	}

	// Return the private key and raw certificate bytes
	return privateKey, cert.Raw, nil
}

3. Initialize the Key Store
Set the paths for the private key and certificate:

spKeyStore := NewLocalKeyStore("./private.key", "./public.cert")

4. Configure the Service Provider
Assign the initialized key store to your SAML service provider:

sp := &saml2.SAMLServiceProvider{
   SPKeyStore: spKeyStore,
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants