aes_ctr_cipher.go 3.8 KB

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