encryption.go 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // Package rfc3962 provides encryption and checksum methods as specified in RFC 3962
  2. package rfc3962
  3. import (
  4. "crypto/rand"
  5. "errors"
  6. "fmt"
  7. "github.com/jcmturner/aescts/v2"
  8. "github.com/jcmturner/gokrb5/v8/crypto/common"
  9. "github.com/jcmturner/gokrb5/v8/crypto/etype"
  10. )
  11. // EncryptData encrypts the data provided using methods specific to the etype provided as defined in RFC 3962.
  12. func EncryptData(key, data []byte, e etype.EType) ([]byte, []byte, error) {
  13. if len(key) != e.GetKeyByteSize() {
  14. return []byte{}, []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
  15. }
  16. ivz := make([]byte, e.GetCypherBlockBitLength()/8)
  17. return aescts.Encrypt(key, ivz, data)
  18. }
  19. // EncryptMessage encrypts the message provided using the methods specific to the etype provided as defined in RFC 3962.
  20. // The encrypted data is concatenated with its integrity hash to create an encrypted message.
  21. func EncryptMessage(key, message []byte, usage uint32, e etype.EType) ([]byte, []byte, error) {
  22. if len(key) != e.GetKeyByteSize() {
  23. return []byte{}, []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
  24. }
  25. //confounder
  26. c := make([]byte, e.GetConfounderByteSize())
  27. _, err := rand.Read(c)
  28. if err != nil {
  29. return []byte{}, []byte{}, fmt.Errorf("could not generate random confounder: %v", err)
  30. }
  31. plainBytes := append(c, message...)
  32. // Derive key for encryption from usage
  33. var k []byte
  34. if usage != 0 {
  35. k, err = e.DeriveKey(key, common.GetUsageKe(usage))
  36. if err != nil {
  37. return []byte{}, []byte{}, fmt.Errorf("error deriving key for encryption: %v", err)
  38. }
  39. }
  40. // Encrypt the data
  41. iv, b, err := e.EncryptData(k, plainBytes)
  42. if err != nil {
  43. return iv, b, fmt.Errorf("error encrypting data: %v", err)
  44. }
  45. // Generate and append integrity hash
  46. ih, err := common.GetIntegrityHash(plainBytes, key, usage, e)
  47. if err != nil {
  48. return iv, b, fmt.Errorf("error encrypting data: %v", err)
  49. }
  50. b = append(b, ih...)
  51. return iv, b, nil
  52. }
  53. // DecryptData decrypts the data provided using the methods specific to the etype provided as defined in RFC 3962.
  54. func DecryptData(key, data []byte, e etype.EType) ([]byte, error) {
  55. if len(key) != e.GetKeyByteSize() {
  56. return []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
  57. }
  58. ivz := make([]byte, e.GetCypherBlockBitLength()/8)
  59. return aescts.Decrypt(key, ivz, data)
  60. }
  61. // DecryptMessage decrypts the message provided using the methods specific to the etype provided as defined in RFC 3962.
  62. // The integrity of the message is also verified.
  63. func DecryptMessage(key, ciphertext []byte, usage uint32, e etype.EType) ([]byte, error) {
  64. //Derive the key
  65. k, err := e.DeriveKey(key, common.GetUsageKe(usage))
  66. if err != nil {
  67. return nil, fmt.Errorf("error deriving key: %v", err)
  68. }
  69. // Strip off the checksum from the end
  70. b, err := e.DecryptData(k, ciphertext[:len(ciphertext)-e.GetHMACBitLength()/8])
  71. if err != nil {
  72. return nil, err
  73. }
  74. //Verify checksum
  75. if !e.VerifyIntegrity(key, ciphertext, b, usage) {
  76. return nil, errors.New("integrity verification failed")
  77. }
  78. //Remove the confounder bytes
  79. return b[e.GetConfounderByteSize():], nil
  80. }