mirror of
https://github.com/fhmq/hmq.git
synced 2026-09-01 23:34:52 +00:00
Plugins support (#46)
* modify * update * add acl * add feature * update dockerfile * add deploy * update * update * plugins * plugins * update * update * update * fixed * remove * fixed * add log * update * fixed * update * fix config * add http api * add http api * resp * add config for work chan * update * fixed * update * disable trace * fixed * change acl * fixed * fixed res * dd * dd * ddd * dd * update * fixed * update * add * fixed * update key * add log * update * format * update * update auth * update * update readme * added * update * fixed * fixed * fix * upade * update * update
This commit is contained in:
+128
@@ -0,0 +1,128 @@
|
||||
// Package rfc8009 provides encryption and checksum methods as specified in RFC 8009
|
||||
package rfc8009
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/jcmturner/aescts.v1"
|
||||
"gopkg.in/jcmturner/gokrb5.v7/crypto/common"
|
||||
"gopkg.in/jcmturner/gokrb5.v7/crypto/etype"
|
||||
"gopkg.in/jcmturner/gokrb5.v7/iana/etypeID"
|
||||
)
|
||||
|
||||
// EncryptData encrypts the data provided using methods specific to the etype provided as defined in RFC 8009.
|
||||
func EncryptData(key, data []byte, e etype.EType) ([]byte, []byte, error) {
|
||||
kl := e.GetKeyByteSize()
|
||||
if e.GetETypeID() == etypeID.AES256_CTS_HMAC_SHA384_192 {
|
||||
kl = 32
|
||||
}
|
||||
if len(key) != kl {
|
||||
return []byte{}, []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
|
||||
}
|
||||
ivz := make([]byte, aes.BlockSize)
|
||||
return aescts.Encrypt(key, ivz, data)
|
||||
}
|
||||
|
||||
// EncryptMessage encrypts the message provided using the methods specific to the etype provided as defined in RFC 8009.
|
||||
// The encrypted data is concatenated with its integrity hash to create an encrypted message.
|
||||
func EncryptMessage(key, message []byte, usage uint32, e etype.EType) ([]byte, []byte, error) {
|
||||
kl := e.GetKeyByteSize()
|
||||
if e.GetETypeID() == etypeID.AES256_CTS_HMAC_SHA384_192 {
|
||||
kl = 32
|
||||
}
|
||||
if len(key) != kl {
|
||||
return []byte{}, []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", kl, len(key))
|
||||
}
|
||||
if len(key) != e.GetKeyByteSize() {
|
||||
}
|
||||
//confounder
|
||||
c := make([]byte, e.GetConfounderByteSize())
|
||||
_, err := rand.Read(c)
|
||||
if err != nil {
|
||||
return []byte{}, []byte{}, fmt.Errorf("could not generate random confounder: %v", err)
|
||||
}
|
||||
plainBytes := append(c, message...)
|
||||
|
||||
// Derive key for encryption from usage
|
||||
var k []byte
|
||||
if usage != 0 {
|
||||
k, err = e.DeriveKey(key, common.GetUsageKe(usage))
|
||||
if err != nil {
|
||||
return []byte{}, []byte{}, fmt.Errorf("error deriving key for encryption: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Encrypt the data
|
||||
iv, b, err := e.EncryptData(k, plainBytes)
|
||||
if err != nil {
|
||||
return iv, b, fmt.Errorf("error encrypting data: %v", err)
|
||||
}
|
||||
|
||||
ivz := make([]byte, e.GetConfounderByteSize())
|
||||
ih, err := GetIntegityHash(ivz, b, key, usage, e)
|
||||
if err != nil {
|
||||
return iv, b, fmt.Errorf("error encrypting data: %v", err)
|
||||
}
|
||||
b = append(b, ih...)
|
||||
return iv, b, nil
|
||||
}
|
||||
|
||||
// DecryptData decrypts the data provided using the methods specific to the etype provided as defined in RFC 8009.
|
||||
func DecryptData(key, data []byte, e etype.EType) ([]byte, error) {
|
||||
kl := e.GetKeyByteSize()
|
||||
if e.GetETypeID() == etypeID.AES256_CTS_HMAC_SHA384_192 {
|
||||
kl = 32
|
||||
}
|
||||
if len(key) != kl {
|
||||
return []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", kl, len(key))
|
||||
}
|
||||
ivz := make([]byte, aes.BlockSize)
|
||||
return aescts.Decrypt(key, ivz, data)
|
||||
}
|
||||
|
||||
// DecryptMessage decrypts the message provided using the methods specific to the etype provided as defined in RFC 8009.
|
||||
// The integrity of the message is also verified.
|
||||
func DecryptMessage(key, ciphertext []byte, usage uint32, e etype.EType) ([]byte, error) {
|
||||
//Derive the key
|
||||
k, err := e.DeriveKey(key, common.GetUsageKe(usage))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error deriving key: %v", err)
|
||||
}
|
||||
// Strip off the checksum from the end
|
||||
b, err := e.DecryptData(k, ciphertext[:len(ciphertext)-e.GetHMACBitLength()/8])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//Verify checksum
|
||||
if !e.VerifyIntegrity(key, ciphertext, b, usage) {
|
||||
return nil, errors.New("integrity verification failed")
|
||||
}
|
||||
//Remove the confounder bytes
|
||||
return b[e.GetConfounderByteSize():], nil
|
||||
}
|
||||
|
||||
// GetIntegityHash returns a keyed integrity hash of the bytes provided as defined in RFC 8009
|
||||
func GetIntegityHash(iv, c, key []byte, usage uint32, e etype.EType) ([]byte, error) {
|
||||
// Generate and append integrity hash
|
||||
// The HMAC is calculated over the cipher state concatenated with the
|
||||
// AES output, instead of being calculated over the confounder and
|
||||
// plaintext. This allows the message receiver to verify the
|
||||
// integrity of the message before decrypting the message.
|
||||
// H = HMAC(Ki, IV | C)
|
||||
ib := append(iv, c...)
|
||||
return common.GetIntegrityHash(ib, key, usage, e)
|
||||
}
|
||||
|
||||
// VerifyIntegrity verifies the integrity of cipertext bytes ct.
|
||||
func VerifyIntegrity(key, ct []byte, usage uint32, etype etype.EType) bool {
|
||||
h := make([]byte, etype.GetHMACBitLength()/8)
|
||||
copy(h, ct[len(ct)-etype.GetHMACBitLength()/8:])
|
||||
ivz := make([]byte, etype.GetConfounderByteSize())
|
||||
ib := append(ivz, ct[:len(ct)-(etype.GetHMACBitLength()/8)]...)
|
||||
expectedMAC, _ := common.GetIntegrityHash(ib, key, usage, etype)
|
||||
return hmac.Equal(h, expectedMAC)
|
||||
}
|
||||
Reference in New Issue
Block a user