Created
September 23, 2016 08:32
-
-
Save PierreZ/a48cb91adfaf1e4753a392916d48924a to your computer and use it in GitHub Desktop.
aes bis
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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