github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/bccsp/pkcs11/aes.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package pkcs11 18 19 import ( 20 "bytes" 21 "crypto/aes" 22 "crypto/cipher" 23 "crypto/rand" 24 "errors" 25 "fmt" 26 "io" 27 ) 28 29 // GetRandomBytes returns len random looking bytes 30 func GetRandomBytes(len int) ([]byte, error) { 31 buffer := make([]byte, len) 32 33 n, err := rand.Read(buffer) 34 if err != nil { 35 return nil, err 36 } 37 if n != len { 38 return nil, fmt.Errorf("Buffer not filled. Requested [%d], got [%d]", len, n) 39 } 40 41 return buffer, nil 42 } 43 44 func pkcs7Padding(src []byte) []byte { 45 padding := aes.BlockSize - len(src)%aes.BlockSize 46 padtext := bytes.Repeat([]byte{byte(padding)}, padding) 47 return append(src, padtext...) 48 } 49 50 func pkcs7UnPadding(src []byte) ([]byte, error) { 51 length := len(src) 52 unpadding := int(src[length-1]) 53 54 if unpadding > aes.BlockSize || unpadding == 0 { 55 return nil, errors.New("Invalid pkcs7 padding (unpadding > aes.BlockSize || unpadding == 0)") 56 } 57 58 pad := src[len(src)-unpadding:] 59 for i := 0; i < unpadding; i++ { 60 if pad[i] != byte(unpadding) { 61 return nil, errors.New("Invalid pkcs7 padding (pad[i] != unpadding)") 62 } 63 } 64 65 return src[:(length - unpadding)], nil 66 } 67 68 func aesCBCEncrypt(key, s []byte) ([]byte, error) { 69 if len(s)%aes.BlockSize != 0 { 70 return nil, errors.New("Invalid plaintext. It must be a multiple of the block size") 71 } 72 73 block, err := aes.NewCipher(key) 74 if err != nil { 75 return nil, err 76 } 77 78 ciphertext := make([]byte, aes.BlockSize+len(s)) 79 iv := ciphertext[:aes.BlockSize] 80 if _, err := io.ReadFull(rand.Reader, iv); err != nil { 81 return nil, err 82 } 83 84 mode := cipher.NewCBCEncrypter(block, iv) 85 mode.CryptBlocks(ciphertext[aes.BlockSize:], s) 86 87 return ciphertext, nil 88 } 89 90 func aesCBCDecrypt(key, src []byte) ([]byte, error) { 91 block, err := aes.NewCipher(key) 92 if err != nil { 93 return nil, err 94 } 95 96 if len(src) < aes.BlockSize { 97 return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size") 98 } 99 iv := src[:aes.BlockSize] 100 src = src[aes.BlockSize:] 101 102 if len(src)%aes.BlockSize != 0 { 103 return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size") 104 } 105 106 mode := cipher.NewCBCDecrypter(block, iv) 107 108 mode.CryptBlocks(src, src) 109 110 return src, nil 111 } 112 113 // AESCBCPKCS7Encrypt combines CBC encryption and PKCS7 padding 114 func AESCBCPKCS7Encrypt(key, src []byte) ([]byte, error) { 115 // First pad 116 tmp := pkcs7Padding(src) 117 118 // Then encrypt 119 return aesCBCEncrypt(key, tmp) 120 } 121 122 // AESCBCPKCS7Decrypt combines CBC decryption and PKCS7 unpadding 123 func AESCBCPKCS7Decrypt(key, src []byte) ([]byte, error) { 124 // First decrypt 125 pt, err := aesCBCDecrypt(key, src) 126 if err != nil { 127 return nil, err 128 } 129 130 // Then remove padding 131 original, err := pkcs7UnPadding(pt) 132 if err != nil { 133 return nil, err 134 } 135 136 return original, nil 137 }