Skip to content

secure local credential management library written in Go.

License

Notifications You must be signed in to change notification settings

snowmerak/local-cred

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

local-cred

local-cred is a secure local credential management library written in Go. It provides a unified interface for managing cryptographic keys and performing encryption/signing operations, leveraging platform-specific security hardware and storage mechanisms.

Features

  • Platform Specific Security:
    • Windows & Linux: Uses TPM 2.0 (Trusted Platform Module) for secure key storage and operations.
    • macOS: Uses the system Keychain for secure key storage.
  • Cryptographic Operations:
    • Encryption (DEK - Data Encryption Key):
      • AES-256-GCM
      • XChaCha20-Poly1305
    • Signing:
      • ECDSA (P-256)
      • Ed25519
      • ML-DSA-87 (Post-Quantum Cryptography)
  • Key Hierarchy:
    • KEK (Key Encryption Key): Protected by the platform (TPM or Keychain). Used to encrypt DEKs and Signing Keys.
    • DEK (Data Encryption Key): Encrypted by KEK. Used to encrypt actual data.
    • Signing Key: Encrypted by KEK. Used to sign data.
  • Secure Memory: Uses memguard to protect sensitive key material in memory (where applicable).

Installation

go get github.com/snowmerak/local-cred

Prerequisites

  • Windows/Linux: A TPM 2.0 module is required (or a simulator for testing).
  • macOS: Access to the system Keychain.

Usage

Windows / Linux (TPM)

On Windows and Linux, local-cred uses the TPM to protect the Key Encryption Key (KEK).

package main

import (
	"fmt"
	"log"

	"github.com/snowmerak/local-cred/keystore/tpm"
)

func main() {
	// 1. Initialize TPM Client
	// Note: In a real application, you might need to configure the TPM transport.
	// This example assumes a default setup or simulator.
	// See tpm.OpenTPM in the library for details on connection.
    // For Windows, it automatically connects to the system TPM.
    
    // Initialize a Store to save the encrypted keys (blobs).
    // You can use the provided BadgerStore, PebbleStore, or implement your own tpm.Store interface.
    
    // Option A: Use BadgerDB
    store, err := tpm.NewBadgerDB("./badger-data")
    // Option B: Use PebbleDB
    // store, err := tpm.NewPebbleDB("./pebble-data")
    if err != nil {
        log.Fatal(err)
    }
    defer store.Close()
    
    client, err := tpm.NewTPMClient() // You might need to pass transport
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

	ops, err := tpm.NewTPMOps(client, store)
	if err != nil {
		log.Fatal(err)
	}
	defer ops.Close()

	kekName := "my-app-kek"

	// 2. Create/Load a Data Encryption Key (DEK)
	// Supported algos: "AES256GCM", "XChaCha20Poly1305"
	encryptor, encryptedDEK, err := ops.CreateDEK(kekName, "AES256GCM")
	if err != nil {
		log.Fatal(err)
	}
    // Save encryptedDEK to your storage for later use
    
	// Encrypt data
	plaintext := []byte("Secret Data")
	ciphertext, err := encryptor.Encrypt(plaintext)
	if err != nil {
		log.Fatal(err)
	}

	// Decrypt data
	decrypted, err := encryptor.Decrypt(ciphertext)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Decrypted: %s\n", decrypted)

    // 3. Create/Load a Signing Key
    // Supported algos: "ECDSA-P256", "Ed25519", "ML-DSA-87"
    signer, encryptedPriv, pubKey, err := ops.CreateSigningKey(kekName, "ML-DSA-87")
    if err != nil {
        log.Fatal(err)
    }
    // Save encryptedPriv and pubKey to your storage

    // Sign data
    msg := []byte("Message to sign")
    signature, err := signer.Sign(msg)
    if err != nil {
        log.Fatal(err)
    }

    // Verify signature
    valid := signer.Verify(msg, signature)
    fmt.Printf("Signature Valid: %v\n", valid)
}

macOS (Keychain)

On macOS, local-cred uses the system Keychain to store the KEK.

package main

import (
	"fmt"
	"log"

	"github.com/snowmerak/local-cred/keystore/keychain"
)

func main() {
	serviceName := "my-app-service"
	client := keychain.NewKeychainClient(serviceName)

	kekName := "my-app-kek"

	// 1. Create/Load a Data Encryption Key (DEK)
	encryptor, encryptedDEK, err := client.CreateDEK(kekName, "XChaCha20Poly1305")
	if err != nil {
		log.Fatal(err)
	}
    // Save encryptedDEK

	// Encrypt/Decrypt...
    // ...

    // 2. Create/Load a Signing Key
    signer, encryptedPriv, pubKey, err := client.CreateSigningKey(kekName, "Ed25519")
    if err != nil {
        log.Fatal(err)
    }
    // Save encryptedPriv and pubKey

    // Sign/Verify...
    // ...
}

Architecture

TPM (Windows/Linux)

The TPM implementation uses the TPM to wrap a "Key Encryption Key" (KEK). This KEK never leaves the TPM in plaintext.

  • KEK Creation: A primary key (SRK) in the TPM is used to wrap a generated AES key (the KEK).
  • DEK/Signing Key Creation: New keys are generated in software (using secure memory), then encrypted (wrapped) by the KEK using the TPM.
  • Usage: To use a key, the encrypted blob is loaded into the TPM, unwrapped by the KEK inside the TPM, and then used for operations.

Keychain (macOS)

The Keychain implementation uses the macOS Keychain to store the KEK securely.

  • KEK Storage: The KEK is stored as a generic password item in the Keychain.
  • Operations: The KEK is retrieved from the Keychain into secure memory (memguard) to perform encryption/decryption of DEKs and Signing Keys in software.

License

MIT License

About

secure local credential management library written in Go.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages