envelope.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package kms
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. )
  6. // CiphertextEnvelope represents a standardized format for storing encrypted data
  7. // along with the metadata needed for decryption. This ensures consistent API
  8. // behavior across all KMS providers.
  9. type CiphertextEnvelope struct {
  10. // Provider identifies which KMS provider was used
  11. Provider string `json:"provider"`
  12. // KeyID is the identifier of the key used for encryption
  13. KeyID string `json:"key_id"`
  14. // Ciphertext is the encrypted data (base64 encoded for JSON compatibility)
  15. Ciphertext string `json:"ciphertext"`
  16. // Version allows for future format changes
  17. Version int `json:"version"`
  18. // ProviderSpecific contains provider-specific metadata if needed
  19. ProviderSpecific map[string]interface{} `json:"provider_specific,omitempty"`
  20. }
  21. // CreateEnvelope creates a ciphertext envelope for consistent KMS provider behavior
  22. func CreateEnvelope(provider, keyID, ciphertext string, providerSpecific map[string]interface{}) ([]byte, error) {
  23. // Validate required fields
  24. if provider == "" {
  25. return nil, fmt.Errorf("provider cannot be empty")
  26. }
  27. if keyID == "" {
  28. return nil, fmt.Errorf("keyID cannot be empty")
  29. }
  30. if ciphertext == "" {
  31. return nil, fmt.Errorf("ciphertext cannot be empty")
  32. }
  33. envelope := CiphertextEnvelope{
  34. Provider: provider,
  35. KeyID: keyID,
  36. Ciphertext: ciphertext,
  37. Version: 1,
  38. ProviderSpecific: providerSpecific,
  39. }
  40. return json.Marshal(envelope)
  41. }
  42. // ParseEnvelope parses a ciphertext envelope to extract key information
  43. func ParseEnvelope(ciphertextBlob []byte) (*CiphertextEnvelope, error) {
  44. if len(ciphertextBlob) == 0 {
  45. return nil, fmt.Errorf("ciphertext blob cannot be empty")
  46. }
  47. // Parse as envelope format
  48. var envelope CiphertextEnvelope
  49. if err := json.Unmarshal(ciphertextBlob, &envelope); err != nil {
  50. return nil, fmt.Errorf("failed to parse ciphertext envelope: %w", err)
  51. }
  52. // Validate required fields
  53. if envelope.Provider == "" {
  54. return nil, fmt.Errorf("envelope missing provider field")
  55. }
  56. if envelope.KeyID == "" {
  57. return nil, fmt.Errorf("envelope missing key_id field")
  58. }
  59. if envelope.Ciphertext == "" {
  60. return nil, fmt.Errorf("envelope missing ciphertext field")
  61. }
  62. if envelope.Version == 0 {
  63. envelope.Version = 1 // Default to version 1
  64. }
  65. return &envelope, nil
  66. }