Skip to content

Instantly share code, notes, and snippets.

@PierreZ
Created September 23, 2016 08:32
Show Gist options
  • Save PierreZ/a48cb91adfaf1e4753a392916d48924a to your computer and use it in GitHub Desktop.
Save PierreZ/a48cb91adfaf1e4753a392916d48924a to your computer and use it in GitHub Desktop.
aes bis
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"github.com/dvsekhvalnov/jose2go/arrays"
)
var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}
// KeyWrap encrypts provided key (CEK) with KEK key using AES Key Wrap (rfc 3394) algorithm
func KeyWrap(cek, kek []byte) ([]byte, error) {
// 1) Initialize variables
a := defaultIV // Set A = IV, an initial value
r := arrays.Slice(cek, 8) // For i = 1 to n
// R[0][i] = P[i]
n := uint64(len(r))
// 2) Calculate intermediate values.
var j, i, t uint64
for j = 0; j < 6; j++ { // For j = 0 to 5
for i = 0; i < n; i++ { // For i=1 to n
t = n*j + i + 1
b, e := aesEnc(kek, arrays.Concat(a, r[i])) // B=AES(K, A | R[i])
if e != nil {
return nil, e
}
a = b[:len(b)/2] // A=MSB(64,B) ^ t where t = (n*j)+i
r[i] = b[len(b)/2:] // R[i] = LSB(64, B)
a = arrays.Xor(a, arrays.UInt64ToBytes(t))
}
}
// 3) Output the results
c := make([][]byte, n+1, n+1)
c[0] = a // Set C[0] = A
for i = 1; i <= n; i++ { // For i = 1 to n
c[i] = r[i-1] // C[i] = R[i]
}
return arrays.Unwrap(c), nil
}
// KeyUnwrap decrypts previously encrypted key (CEK) with KEK key using AES Key Wrap (rfc 3394) algorithm
func KeyUnwrap(encryptedCek, kek []byte) ([]byte, error) {
// 1) Initialize variables
c := arrays.Slice(encryptedCek, 8)
a := c[0] // Set A = C[0]
r := make([][]byte, len(c)-1)
for i := 1; i < len(c); i++ { // For i = 1 to n
r[i-1] = c[i] // R[i] = C[i]
}
n := uint64(len(r))
// 2) Calculate intermediate values
var t, j uint64
for j = 6; j > 0; j-- { // For j = 5 to 0
for i := n; i > 0; i-- { // For i = n to 1
t = n*(j-1) + i
a = arrays.Xor(a, arrays.UInt64ToBytes(t))
b, e := aesDec(kek, arrays.Concat(a, r[i-1])) // B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
if e != nil {
return nil, e
}
a = b[:len(b)/2] // A = MSB(64, B)
r[i-1] = b[len(b)/2:] // R[i] = LSB(64, B)
}
}
// 3) Output the results
if !hmac.Equal(defaultIV, a) { // If A is an appropriate initial value
return nil, errors.New("aes.KeyUnwrap(): integrity check failed.")
}
// For i = 1 to n
return arrays.Unwrap(r), nil // P[i] = R[i]
}
func aesEnc(kek, plainText []byte) (cipherText []byte, err error) {
var block cipher.Block
if block, err = aes.NewCipher(kek); err != nil {
return nil, err
}
cipherText = make([]byte, len(plainText))
NewECBEncrypter(block).CryptBlocks(cipherText, plainText)
return cipherText, nil
}
func aesDec(kek, cipherText []byte) (plainText []byte, err error) {
var block cipher.Block
if block, err = aes.NewCipher(kek); err != nil {
return nil, err
}
plainText = make([]byte, len(cipherText))
NewECBDecrypter(block).CryptBlocks(plainText, cipherText)
return plainText, nil
}
// GenerateRandomBytes returns securely generated random bytes.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
// Note that err == nil only if we read len(b) bytes.
if err != nil {
return nil, err
}
return b, nil
}
func PKCS7Padding(data []byte) []byte {
blockSize := 8
padding := blockSize - len(data)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padtext...)
}
func main() {
kek := []byte("cfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcf")
yolo := []byte("mon sdejdfkslshjfdsiklfjdskfjdskosdalret")
data, err := GenerateRandomBytes(8)
if err != nil {
fmt.Println(err)
}
data = append(yolo, data...)
padded := PKCS7Padding(data)
fmt.Println(len(padded) % 8)
wrapped, _ := KeyWrap(padded, kek)
fmt.Println(hex.EncodeToString(wrapped))
}
type ecb struct {
b cipher.Block
}
type ecbEncrypter ecb
type ecbDecrypter ecb
// NewECBEncrypter creates BlockMode for AES encryption in ECB mode
func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
return &ecbEncrypter{b: b}
}
// NewECBDecrypter creates BlockMode for AES decryption in ECB mode
func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
return &ecbDecrypter{b: b}
}
func (x *ecbEncrypter) BlockSize() int { return x.b.BlockSize() }
func (x *ecbDecrypter) BlockSize() int { return x.b.BlockSize() }
func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
bs := x.BlockSize()
if len(src)%bs != 0 {
panic("ecbDecrypter.CryptBlocks(): input not full blocks")
}
if len(dst) < len(src) {
panic("ecbDecrypter.CryptBlocks(): output smaller than input")
}
if len(src) == 0 {
return
}
for len(src) > 0 {
x.b.Decrypt(dst, src)
src = src[bs:]
}
}
func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
bs := x.BlockSize()
if len(src)%bs != 0 {
panic("ecbEncrypter.CryptBlocks(): input not full blocks")
}
if len(dst) < len(src) {
panic("ecbEncrypter.CryptBlocks(): output smaller than input")
}
if len(src) == 0 {
return
}
for len(src) > 0 {
x.b.Encrypt(dst, src)
src = src[bs:]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment