cipher.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package fte
  2. import (
  3. "crypto/rand"
  4. "encoding/binary"
  5. "errors"
  6. "io"
  7. "math/big"
  8. )
  9. var (
  10. ErrInsufficientCapacity = errors.New("fte: insufficient capacity")
  11. )
  12. type Cipher struct {
  13. dfa *DFA
  14. enc *Encrypter
  15. dec *Decrypter
  16. }
  17. // NewCipher returns a new instance of Cipher.
  18. func NewCipher(regex string, n int) (_ *Cipher, err error) {
  19. var c Cipher
  20. if c.enc, err = NewEncrypter(); err != nil {
  21. return nil, err
  22. } else if c.dec, err = NewDecrypter(); err != nil {
  23. return nil, err
  24. } else if c.dfa, err = NewDFA(regex, n); err != nil {
  25. return nil, err
  26. }
  27. return &c, nil
  28. }
  29. func (c *Cipher) Close() error {
  30. if c.dfa != nil {
  31. err := c.dfa.Close()
  32. c.dfa = nil
  33. return err
  34. }
  35. return nil
  36. }
  37. // Capacity returns the capacity left in the encoder.
  38. func (c *Cipher) Capacity() int {
  39. return c.dfa.Capacity()
  40. }
  41. // Encrypt encrypts plaintext into ciphertext.
  42. func (c *Cipher) Encrypt(plaintext []byte) (ciphertext []byte, err error) {
  43. if len(plaintext) == 0 {
  44. return nil, nil
  45. }
  46. if ciphertext, err = c.enc.Encrypt(plaintext); err != nil {
  47. return nil, err
  48. }
  49. maximumBytesToRank := c.Capacity()
  50. unrank_payload_len := (maximumBytesToRank - COVERTEXT_HEADER_LEN_CIPHERTTEXT)
  51. if len(ciphertext) < unrank_payload_len {
  52. unrank_payload_len = len(ciphertext)
  53. }
  54. if unrank_payload_len <= 0 {
  55. return nil, ErrInsufficientCapacity
  56. }
  57. msg_len_header := make([]byte, 16)
  58. if _, err := io.ReadFull(rand.Reader, msg_len_header[:8]); err != nil {
  59. return nil, err
  60. }
  61. binary.BigEndian.PutUint64(msg_len_header[8:], uint64(unrank_payload_len))
  62. encryptedHeader := make([]byte, len(msg_len_header))
  63. c.enc.block.Encrypt(encryptedHeader, msg_len_header)
  64. msg_len_header = encryptedHeader
  65. unrank_payload := encryptedHeader
  66. if len(ciphertext) <= maximumBytesToRank-16 {
  67. unrank_payload = append(unrank_payload, ciphertext...)
  68. } else {
  69. unrank_payload = append(unrank_payload, ciphertext[:maximumBytesToRank-16]...)
  70. }
  71. random_padding_len := maximumBytesToRank - len(unrank_payload)
  72. if random_padding_len > 0 {
  73. randomPadding := make([]byte, random_padding_len)
  74. if _, err := io.ReadFull(rand.Reader, randomPadding); err != nil {
  75. return nil, err
  76. }
  77. unrank_payload = append(unrank_payload, randomPadding...)
  78. }
  79. var unrankValue big.Int
  80. unrankValue.SetBytes(unrank_payload)
  81. formatted_covertext_header, err := c.dfa.Unrank(&unrankValue)
  82. if err != nil {
  83. return nil, err
  84. }
  85. var unformatted_covertext_body []byte
  86. if len(ciphertext) > maximumBytesToRank-16 {
  87. unformatted_covertext_body = ciphertext[maximumBytesToRank-16:]
  88. }
  89. return append([]byte(formatted_covertext_header), unformatted_covertext_body...), nil
  90. }
  91. // Decrypt decrypts ciphertext into plaintext.
  92. // Returns ErrShortCiphertext if the ciphertext is too short to be decrypted.
  93. func (c *Cipher) Decrypt(ciphertext []byte) (plaintext, remainder []byte, err error) {
  94. if len(ciphertext) < c.dfa.N() {
  95. return nil, nil, ErrShortCiphertext
  96. }
  97. maximumBytesToRank := c.Capacity()
  98. rank_payload, err := c.dfa.Rank(string(ciphertext[:c.dfa.N()]))
  99. if err != nil {
  100. return nil, nil, err
  101. }
  102. X := rank_payload.Bytes()
  103. if len(X) < maximumBytesToRank {
  104. X = append(make([]byte, maximumBytesToRank-len(X)), X...)
  105. }
  106. msg_len_header := make([]byte, 16)
  107. c.dec.block.Decrypt(msg_len_header, X[:16])
  108. msg_len := binary.BigEndian.Uint64(msg_len_header[8:16])
  109. retval := X[16 : 16+msg_len]
  110. retval = append(retval, ciphertext[c.dfa.N():]...)
  111. ctxt_len := c.dec.CiphertextLen(retval)
  112. var remaining_buffer []byte
  113. if len(retval) > ctxt_len {
  114. remaining_buffer = retval[ctxt_len:]
  115. }
  116. if len(retval) > ctxt_len {
  117. retval = retval[:ctxt_len]
  118. }
  119. if retval, err = c.dec.Decrypt(retval); err != nil {
  120. return nil, nil, err
  121. }
  122. return retval, remaining_buffer, nil
  123. }