github.com/signintech/pdft@v0.5.0/minigopdf/pdf_protection.go (about) 1 package gopdf 2 3 import ( 4 "bytes" 5 "crypto/md5" 6 "crypto/rc4" 7 "encoding/binary" 8 "math/rand" 9 "time" 10 ) 11 12 const ( 13 //PermissionsPrint setProtection print 14 PermissionsPrint = 4 15 //PermissionsModify setProtection modify 16 PermissionsModify = 8 17 //PermissionsCopy setProtection copy 18 PermissionsCopy = 16 19 //PermissionsAnnotForms setProtection annot-forms 20 PermissionsAnnotForms = 32 21 ) 22 23 var protectionPadding = []byte{ 24 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, 25 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A, 26 } 27 28 // PDFProtection protection in pdf 29 type PDFProtection struct { 30 encrypted bool //whether document is protected 31 uValue []byte //U entry in pdf document 32 oValue []byte //O entry in pdf document 33 pValue int //P entry in pdf document 34 //var $enc_obj_id; //encryption object id 35 encryptionKey []byte 36 } 37 38 // SetProtection set protection infomation 39 func (p *PDFProtection) SetProtection(permissions int, userPass []byte, ownerPass []byte) error { 40 return p.setProtection(permissions, userPass, ownerPass) 41 } 42 43 func (p *PDFProtection) setProtection(permissions int, userPass []byte, ownerPass []byte) error { 44 protection := 192 | permissions 45 if ownerPass == nil || len(ownerPass) == 0 { 46 ownerPass = p.randomPass(24) 47 } 48 return p.generateEncryptionKey(userPass, ownerPass, protection) 49 } 50 51 func (p *PDFProtection) generateEncryptionKey(userPass []byte, ownerPass []byte, protection int) error { 52 53 userPass = append(userPass, protectionPadding...) 54 userPassWithPadding := userPass[0:32] 55 ownerPass = append(ownerPass, protectionPadding...) 56 ownerPassWithPadding := ownerPass[0:32] 57 58 //oValue 59 oValue, err := p.createOValue(userPassWithPadding, ownerPassWithPadding) 60 if err != nil { 61 return err 62 } 63 p.oValue = oValue 64 65 uValue, err := p.createUValue(userPassWithPadding, oValue, protection) 66 if err != nil { 67 return err 68 } 69 p.uValue = uValue 70 p.pValue = -((protection ^ 255) + 1) 71 72 return nil 73 } 74 75 // EncryptionObj get Encryption Object 76 func (p *PDFProtection) EncryptionObj() *EncryptionObj { 77 return p.encryptionObj() 78 } 79 80 func (p *PDFProtection) encryptionObj() *EncryptionObj { 81 var en EncryptionObj 82 en.oValue = p.oValue 83 en.pValue = p.pValue 84 en.uValue = p.uValue 85 return &en 86 } 87 88 func (p *PDFProtection) createOValue(userPassWithPadding []byte, ownerPassWithPadding []byte) ([]byte, error) { 89 tmp := md5.Sum(ownerPassWithPadding) 90 ownerRC4key := tmp[0:5] 91 cip, err := rc4.NewCipher(ownerRC4key) 92 if err != nil { 93 return nil, err 94 } 95 dest := make([]byte, len(userPassWithPadding)) 96 cip.XORKeyStream(dest, userPassWithPadding) 97 return dest, nil 98 } 99 100 func (p *PDFProtection) createUValue(userPassWithPadding []byte, oValue []byte, protection int) ([]byte, error) { 101 102 var tmp bytes.Buffer 103 tmp.Write(userPassWithPadding) 104 tmp.Write(oValue) 105 tmp.WriteByte(byte(protection)) 106 tmp.WriteByte(byte(0xff)) 107 tmp.WriteByte(byte(0xff)) 108 tmp.WriteByte(byte(0xff)) 109 110 tmp2 := md5.Sum(tmp.Bytes()) 111 p.encryptionKey = tmp2[0:5] 112 cip, err := rc4.NewCipher(p.encryptionKey) 113 if err != nil { 114 return nil, err 115 } 116 dest := make([]byte, len(protectionPadding)) 117 cip.XORKeyStream(dest, protectionPadding) 118 return dest, nil 119 } 120 121 func (p *PDFProtection) randomPass(strlen int) []byte { 122 rand.Seed(time.Now().UTC().UnixNano()) 123 const chars = "abcdef0123456789" 124 result := make([]byte, strlen) 125 for i := 0; i < strlen; i++ { 126 result[i] = chars[rand.Intn(len(chars))] 127 } 128 return result 129 } 130 131 // Objectkey create object key from ObjID 132 func (p *PDFProtection) Objectkey(objID int) []byte { 133 return p.objectkey(objID) 134 } 135 136 func (p *PDFProtection) objectkey(n int) []byte { 137 tmp := make([]byte, 8, 8) 138 binary.LittleEndian.PutUint32(tmp, uint32(n)) 139 tmp2 := append(p.encryptionKey, tmp[0], tmp[1], tmp[2], 0, 0) 140 tmp3 := md5.Sum(tmp2) 141 return tmp3[0:10] 142 } 143 144 func rc4Cip(key []byte, src []byte) ([]byte, error) { 145 cip, err := rc4.NewCipher(key) 146 if err != nil { 147 return nil, err 148 } 149 dest := make([]byte, len(src)) 150 cip.XORKeyStream(dest, src) 151 return dest, nil 152 }