protect.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright (c) 2013-2014 Kurt Jung (Gmail: kurt.w.jung)
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. // PDF protection is adapted from the work of Klemen VODOPIVEC for the fpdf
  17. // product.
  18. package gofpdf
  19. import (
  20. "crypto/md5"
  21. "crypto/rc4"
  22. "encoding/binary"
  23. "math/rand"
  24. )
  25. // Advisory bitflag constants that control document activities
  26. const (
  27. CnProtectPrint = 4
  28. CnProtectModify = 8
  29. CnProtectCopy = 16
  30. CnProtectAnnotForms = 32
  31. )
  32. type protectType struct {
  33. encrypted bool
  34. uValue []byte
  35. oValue []byte
  36. pValue int
  37. padding []byte
  38. encryptionKey []byte
  39. objNum int
  40. rc4cipher *rc4.Cipher
  41. rc4n uint32 // Object number associated with rc4 cipher
  42. }
  43. func (p *protectType) rc4(n uint32, buf *[]byte) {
  44. if p.rc4cipher == nil || p.rc4n != n {
  45. p.rc4cipher, _ = rc4.NewCipher(p.objectKey(n))
  46. p.rc4n = n
  47. }
  48. p.rc4cipher.XORKeyStream(*buf, *buf)
  49. }
  50. func (p *protectType) objectKey(n uint32) []byte {
  51. var nbuf, b []byte
  52. nbuf = make([]byte, 8, 8)
  53. binary.LittleEndian.PutUint32(nbuf, n)
  54. b = append(b, p.encryptionKey...)
  55. b = append(b, nbuf[0], nbuf[1], nbuf[2], 0, 0)
  56. s := md5.Sum(b)
  57. return s[0:10]
  58. }
  59. func oValueGen(userPass, ownerPass []byte) (v []byte) {
  60. var c *rc4.Cipher
  61. tmp := md5.Sum(ownerPass)
  62. c, _ = rc4.NewCipher(tmp[0:5])
  63. size := len(userPass)
  64. v = make([]byte, size, size)
  65. c.XORKeyStream(v, userPass)
  66. return
  67. }
  68. func (p *protectType) uValueGen() (v []byte) {
  69. var c *rc4.Cipher
  70. c, _ = rc4.NewCipher(p.encryptionKey)
  71. size := len(p.padding)
  72. v = make([]byte, size, size)
  73. c.XORKeyStream(v, p.padding)
  74. return
  75. }
  76. func (p *protectType) setProtection(privFlag byte, userPassStr, ownerPassStr string) {
  77. privFlag = 192 | (privFlag & (CnProtectCopy | CnProtectModify | CnProtectPrint | CnProtectAnnotForms))
  78. p.padding = []byte{
  79. 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
  80. 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
  81. 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
  82. 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,
  83. }
  84. userPass := []byte(userPassStr)
  85. var ownerPass []byte
  86. if ownerPassStr == "" {
  87. ownerPass = make([]byte, 8, 8)
  88. binary.LittleEndian.PutUint64(ownerPass, uint64(rand.Int63()))
  89. } else {
  90. ownerPass = []byte(ownerPassStr)
  91. }
  92. userPass = append(userPass, p.padding...)[0:32]
  93. ownerPass = append(ownerPass, p.padding...)[0:32]
  94. p.encrypted = true
  95. p.oValue = oValueGen(userPass, ownerPass)
  96. var buf []byte
  97. buf = append(buf, userPass...)
  98. buf = append(buf, p.oValue...)
  99. buf = append(buf, privFlag, 0xff, 0xff, 0xff)
  100. sum := md5.Sum(buf)
  101. p.encryptionKey = sum[0:5]
  102. p.uValue = p.uValueGen()
  103. p.pValue = -(int(privFlag^255) + 1)
  104. }