cipher.go raw
1 package pkcs8
2
3 import (
4 "bytes"
5 "crypto/cipher"
6 "encoding/asn1"
7 )
8
9 type cipherWithBlock struct {
10 oid asn1.ObjectIdentifier
11 ivSize int
12 keySize int
13 newBlock func(key []byte) (cipher.Block, error)
14 }
15
16 func (c cipherWithBlock) IVSize() int {
17 return c.ivSize
18 }
19
20 func (c cipherWithBlock) KeySize() int {
21 return c.keySize
22 }
23
24 func (c cipherWithBlock) OID() asn1.ObjectIdentifier {
25 return c.oid
26 }
27
28 func (c cipherWithBlock) Encrypt(key, iv, plaintext []byte) ([]byte, error) {
29 block, err := c.newBlock(key)
30 if err != nil {
31 return nil, err
32 }
33 return cbcEncrypt(block, key, iv, plaintext)
34 }
35
36 func (c cipherWithBlock) Decrypt(key, iv, ciphertext []byte) ([]byte, error) {
37 block, err := c.newBlock(key)
38 if err != nil {
39 return nil, err
40 }
41 return cbcDecrypt(block, key, iv, ciphertext)
42 }
43
44 func cbcEncrypt(block cipher.Block, key, iv, plaintext []byte) ([]byte, error) {
45 mode := cipher.NewCBCEncrypter(block, iv)
46 paddingLen := block.BlockSize() - (len(plaintext) % block.BlockSize())
47 ciphertext := make([]byte, len(plaintext)+paddingLen)
48 copy(ciphertext, plaintext)
49 copy(ciphertext[len(plaintext):], bytes.Repeat([]byte{byte(paddingLen)}, paddingLen))
50 mode.CryptBlocks(ciphertext, ciphertext)
51 return ciphertext, nil
52 }
53
54 func cbcDecrypt(block cipher.Block, key, iv, ciphertext []byte) ([]byte, error) {
55 mode := cipher.NewCBCDecrypter(block, iv)
56 plaintext := make([]byte, len(ciphertext))
57 mode.CryptBlocks(plaintext, ciphertext)
58 // TODO: remove padding
59 return plaintext, nil
60 }
61