github.com/aliyun/aliyun-oss-go-sdk@v3.0.2+incompatible/oss/crypto/aes_ctr_cipher.go (about) 1 package osscrypto 2 3 import ( 4 "io" 5 ) 6 7 const ( 8 aesKeySize = 32 9 ivSize = 16 10 ) 11 12 // aesCtrCipherBuilder for building ContentCipher 13 type aesCtrCipherBuilder struct { 14 MasterCipher MasterCipher 15 } 16 17 // aesCtrCipher will use aes ctr algorithm 18 type aesCtrCipher struct { 19 CipherData CipherData 20 Cipher Cipher 21 } 22 23 // CreateAesCtrCipher creates ContentCipherBuilder 24 func CreateAesCtrCipher(cipher MasterCipher) ContentCipherBuilder { 25 return aesCtrCipherBuilder{MasterCipher: cipher} 26 } 27 28 // createCipherData create CipherData for encrypt object data 29 func (builder aesCtrCipherBuilder) createCipherData() (CipherData, error) { 30 var cd CipherData 31 var err error 32 err = cd.RandomKeyIv(aesKeySize, ivSize) 33 if err != nil { 34 return cd, err 35 } 36 37 cd.WrapAlgorithm = builder.MasterCipher.GetWrapAlgorithm() 38 cd.CEKAlgorithm = AesCtrAlgorithm 39 cd.MatDesc = builder.MasterCipher.GetMatDesc() 40 41 // EncryptedKey 42 cd.EncryptedKey, err = builder.MasterCipher.Encrypt(cd.Key) 43 if err != nil { 44 return cd, err 45 } 46 47 // EncryptedIV 48 cd.EncryptedIV, err = builder.MasterCipher.Encrypt(cd.IV) 49 if err != nil { 50 return cd, err 51 } 52 53 return cd, nil 54 } 55 56 // contentCipherCD is used to create ContentCipher with CipherData 57 func (builder aesCtrCipherBuilder) contentCipherCD(cd CipherData) (ContentCipher, error) { 58 cipher, err := newAesCtr(cd) 59 if err != nil { 60 return nil, err 61 } 62 63 return &aesCtrCipher{ 64 CipherData: cd, 65 Cipher: cipher, 66 }, nil 67 } 68 69 // ContentCipher is used to create ContentCipher interface 70 func (builder aesCtrCipherBuilder) ContentCipher() (ContentCipher, error) { 71 cd, err := builder.createCipherData() 72 if err != nil { 73 return nil, err 74 } 75 return builder.contentCipherCD(cd) 76 } 77 78 // ContentCipherEnv is used to create a decrption ContentCipher from Envelope 79 func (builder aesCtrCipherBuilder) ContentCipherEnv(envelope Envelope) (ContentCipher, error) { 80 var cd CipherData 81 cd.EncryptedKey = make([]byte, len(envelope.CipherKey)) 82 copy(cd.EncryptedKey, []byte(envelope.CipherKey)) 83 84 plainKey, err := builder.MasterCipher.Decrypt([]byte(envelope.CipherKey)) 85 if err != nil { 86 return nil, err 87 } 88 cd.Key = make([]byte, len(plainKey)) 89 copy(cd.Key, plainKey) 90 91 cd.EncryptedIV = make([]byte, len(envelope.IV)) 92 copy(cd.EncryptedIV, []byte(envelope.IV)) 93 94 plainIV, err := builder.MasterCipher.Decrypt([]byte(envelope.IV)) 95 if err != nil { 96 return nil, err 97 } 98 99 cd.IV = make([]byte, len(plainIV)) 100 copy(cd.IV, plainIV) 101 102 cd.MatDesc = envelope.MatDesc 103 cd.WrapAlgorithm = envelope.WrapAlg 104 cd.CEKAlgorithm = envelope.CEKAlg 105 106 return builder.contentCipherCD(cd) 107 } 108 109 // GetMatDesc is used to get MasterCipher's MatDesc 110 func (builder aesCtrCipherBuilder) GetMatDesc() string { 111 return builder.MasterCipher.GetMatDesc() 112 } 113 114 // EncryptContents will generate a random key and iv and encrypt the data using ctr 115 func (cc *aesCtrCipher) EncryptContent(src io.Reader) (io.ReadCloser, error) { 116 reader := cc.Cipher.Encrypt(src) 117 return &CryptoEncrypter{Body: src, Encrypter: reader}, nil 118 } 119 120 // DecryptContent is used to decrypt object using ctr 121 func (cc *aesCtrCipher) DecryptContent(src io.Reader) (io.ReadCloser, error) { 122 reader := cc.Cipher.Decrypt(src) 123 return &CryptoDecrypter{Body: src, Decrypter: reader}, nil 124 } 125 126 // GetCipherData is used to get cipher data information 127 func (cc *aesCtrCipher) GetCipherData() *CipherData { 128 return &(cc.CipherData) 129 } 130 131 // GetCipherData returns cipher data 132 func (cc *aesCtrCipher) GetEncryptedLen(plainTextLen int64) int64 { 133 // AES CTR encryption mode does not change content length 134 return plainTextLen 135 } 136 137 // GetAlignLen is used to get align length 138 func (cc *aesCtrCipher) GetAlignLen() int { 139 return len(cc.CipherData.IV) 140 } 141 142 // Clone is used to create a new aesCtrCipher from itself 143 func (cc *aesCtrCipher) Clone(cd CipherData) (ContentCipher, error) { 144 cipher, err := newAesCtr(cd) 145 if err != nil { 146 return nil, err 147 } 148 149 return &aesCtrCipher{ 150 CipherData: cd, 151 Cipher: cipher, 152 }, nil 153 }