You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.0 KiB

4 years ago
  1. package coscrypto
  2. import (
  3. "io"
  4. )
  5. const (
  6. aesKeySize = 32
  7. ivSize = 16
  8. )
  9. type aesCtrCipherBuilder struct {
  10. MasterCipher MasterCipher
  11. }
  12. type aesCtrCipher struct {
  13. CipherData CipherData
  14. Cipher Cipher
  15. }
  16. func CreateAesCtrBuilder(cipher MasterCipher) ContentCipherBuilder {
  17. return aesCtrCipherBuilder{MasterCipher: cipher}
  18. }
  19. func (builder aesCtrCipherBuilder) createCipherData() (CipherData, error) {
  20. var cd CipherData
  21. var err error
  22. err = cd.RandomKeyIv(aesKeySize, ivSize)
  23. if err != nil {
  24. return cd, err
  25. }
  26. cd.WrapAlgorithm = builder.MasterCipher.GetWrapAlgorithm()
  27. cd.CEKAlgorithm = AesCtrAlgorithm
  28. cd.MatDesc = builder.MasterCipher.GetMatDesc()
  29. // EncryptedKey
  30. cd.EncryptedKey, err = builder.MasterCipher.Encrypt(cd.Key)
  31. if err != nil {
  32. return cd, err
  33. }
  34. // EncryptedIV
  35. cd.EncryptedIV, err = builder.MasterCipher.Encrypt(cd.IV)
  36. if err != nil {
  37. return cd, err
  38. }
  39. return cd, nil
  40. }
  41. func (builder aesCtrCipherBuilder) contentCipherCD(cd CipherData) (ContentCipher, error) {
  42. cipher, err := newAesCtr(cd)
  43. if err != nil {
  44. return nil, err
  45. }
  46. return &aesCtrCipher{
  47. CipherData: cd,
  48. Cipher: cipher,
  49. }, nil
  50. }
  51. func (builder aesCtrCipherBuilder) ContentCipher() (ContentCipher, error) {
  52. cd, err := builder.createCipherData()
  53. if err != nil {
  54. return nil, err
  55. }
  56. return builder.contentCipherCD(cd)
  57. }
  58. func (builder aesCtrCipherBuilder) ContentCipherEnv(envelope Envelope) (ContentCipher, error) {
  59. var cd CipherData
  60. cd.EncryptedKey = make([]byte, len(envelope.CipherKey))
  61. copy(cd.EncryptedKey, []byte(envelope.CipherKey))
  62. plainKey, err := builder.MasterCipher.Decrypt([]byte(envelope.CipherKey))
  63. if err != nil {
  64. return nil, err
  65. }
  66. cd.Key = make([]byte, len(plainKey))
  67. copy(cd.Key, plainKey)
  68. cd.EncryptedIV = make([]byte, len(envelope.IV))
  69. copy(cd.EncryptedIV, []byte(envelope.IV))
  70. plainIV, err := builder.MasterCipher.Decrypt([]byte(envelope.IV))
  71. if err != nil {
  72. return nil, err
  73. }
  74. cd.IV = make([]byte, len(plainIV))
  75. copy(cd.IV, plainIV)
  76. cd.MatDesc = envelope.MatDesc
  77. cd.WrapAlgorithm = envelope.WrapAlg
  78. cd.CEKAlgorithm = envelope.CEKAlg
  79. return builder.contentCipherCD(cd)
  80. }
  81. func (builder aesCtrCipherBuilder) GetMatDesc() string {
  82. return builder.MasterCipher.GetMatDesc()
  83. }
  84. func (cc *aesCtrCipher) EncryptContent(src io.Reader) (io.ReadCloser, error) {
  85. reader := cc.Cipher.Encrypt(src)
  86. return &CryptoEncrypter{Body: src, Encrypter: reader}, nil
  87. }
  88. func (cc *aesCtrCipher) DecryptContent(src io.Reader) (io.ReadCloser, error) {
  89. reader := cc.Cipher.Decrypt(src)
  90. return &CryptoDecrypter{Body: src, Decrypter: reader}, nil
  91. }
  92. func (cc *aesCtrCipher) GetCipherData() *CipherData {
  93. return &(cc.CipherData)
  94. }
  95. func (cc *aesCtrCipher) GetEncryptedLen(plainTextLen int64) int64 {
  96. return plainTextLen
  97. }
  98. func (cc *aesCtrCipher) GetAlignLen() int {
  99. return len(cc.CipherData.IV)
  100. }
  101. func (cc *aesCtrCipher) Clone(cd CipherData) (ContentCipher, error) {
  102. cipher, err := newAesCtr(cd)
  103. if err != nil {
  104. return nil, err
  105. }
  106. return &aesCtrCipher{
  107. CipherData: cd,
  108. Cipher: cipher,
  109. }, nil
  110. }