github.com/pdfcpu/pdfcpu@v0.11.1/pkg/api/crypto.go (about) 1 /* 2 Copyright 2020 The pdfcpu Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package api 18 19 import ( 20 "io" 21 "os" 22 23 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model" 24 "github.com/pkg/errors" 25 ) 26 27 // Encrypt reads a PDF stream from rs and writes the encrypted PDF stream to w. 28 // A configuration containing at least the current passwords is required. 29 func Encrypt(rs io.ReadSeeker, w io.Writer, conf *model.Configuration) error { 30 if rs == nil { 31 return errors.New("pdfcpu: Encrypt: missing rs") 32 } 33 34 if conf == nil { 35 return errors.New("pdfcpu: missing configuration for encryption") 36 } 37 conf.Cmd = model.ENCRYPT 38 39 return Optimize(rs, w, conf) 40 } 41 42 // EncryptFile encrypts inFile and writes the result to outFile. 43 // A configuration containing at least the current passwords is required. 44 func EncryptFile(inFile, outFile string, conf *model.Configuration) (err error) { 45 if conf == nil { 46 return errors.New("pdfcpu: missing configuration for encryption") 47 } 48 conf.Cmd = model.ENCRYPT 49 50 var f1, f2 *os.File 51 52 if f1, err = os.Open(inFile); err != nil { 53 return err 54 } 55 56 tmpFile := inFile + ".tmp" 57 if outFile != "" && inFile != outFile { 58 tmpFile = outFile 59 logWritingTo(outFile) 60 } else { 61 logWritingTo(inFile) 62 } 63 64 if f2, err = os.Create(tmpFile); err != nil { 65 f1.Close() 66 return err 67 } 68 69 defer func() { 70 if err != nil { 71 f2.Close() 72 f1.Close() 73 os.Remove(tmpFile) 74 return 75 } 76 if err = f2.Close(); err != nil { 77 return 78 } 79 if err = f1.Close(); err != nil { 80 return 81 } 82 if outFile == "" || inFile == outFile { 83 err = os.Rename(tmpFile, inFile) 84 } 85 }() 86 87 return Encrypt(f1, f2, conf) 88 } 89 90 // Decrypt reads a PDF stream from rs and writes the encrypted PDF stream to w. 91 // A configuration containing at least the current passwords is required. 92 func Decrypt(rs io.ReadSeeker, w io.Writer, conf *model.Configuration) error { 93 if rs == nil { 94 return errors.New("pdfcpu: Decrypt: missing rs") 95 } 96 97 if conf == nil { 98 return errors.New("pdfcpu: missing configuration for decryption") 99 } 100 conf.Cmd = model.DECRYPT 101 102 return Optimize(rs, w, conf) 103 } 104 105 // DecryptFile decrypts inFile and writes the result to outFile. 106 // A configuration containing at least the current passwords is required. 107 func DecryptFile(inFile, outFile string, conf *model.Configuration) (err error) { 108 if conf == nil { 109 return errors.New("pdfcpu: missing configuration for decryption") 110 } 111 conf.Cmd = model.DECRYPT 112 113 var f1, f2 *os.File 114 115 if f1, err = os.Open(inFile); err != nil { 116 return err 117 } 118 119 tmpFile := inFile + ".tmp" 120 if outFile != "" && inFile != outFile { 121 tmpFile = outFile 122 logWritingTo(outFile) 123 } else { 124 logWritingTo(inFile) 125 } 126 127 if f2, err = os.Create(tmpFile); err != nil { 128 f1.Close() 129 return err 130 } 131 132 defer func() { 133 if err != nil { 134 f2.Close() 135 f1.Close() 136 os.Remove(tmpFile) 137 return 138 } 139 if err = f2.Close(); err != nil { 140 return 141 } 142 if err = f1.Close(); err != nil { 143 return 144 } 145 if outFile == "" || inFile == outFile { 146 err = os.Rename(tmpFile, inFile) 147 } 148 }() 149 150 return Decrypt(f1, f2, conf) 151 } 152 153 // ChangeUserPassword reads a PDF stream from rs, changes the user password and writes the encrypted PDF stream to w. 154 // A configuration containing the current passwords is required. 155 func ChangeUserPassword(rs io.ReadSeeker, w io.Writer, pwOld, pwNew string, conf *model.Configuration) error { 156 if rs == nil { 157 return errors.New("pdfcpu: ChangeUserPassword: missing rs") 158 } 159 160 if conf == nil { 161 return errors.New("pdfcpu: missing configuration for change user password") 162 } 163 164 conf.Cmd = model.CHANGEUPW 165 conf.UserPW = pwOld 166 conf.UserPWNew = &pwNew 167 168 return Optimize(rs, w, conf) 169 } 170 171 // ChangeUserPasswordFile reads inFile, changes the user password and writes the result to outFile. 172 // A configuration containing the current passwords is required. 173 func ChangeUserPasswordFile(inFile, outFile string, pwOld, pwNew string, conf *model.Configuration) (err error) { 174 if conf == nil { 175 return errors.New("pdfcpu: missing configuration for change user password") 176 } 177 178 conf.Cmd = model.CHANGEUPW 179 conf.UserPW = pwOld 180 conf.UserPWNew = &pwNew 181 182 var f1, f2 *os.File 183 184 if f1, err = os.Open(inFile); err != nil { 185 return err 186 } 187 188 tmpFile := inFile + ".tmp" 189 if outFile != "" && inFile != outFile { 190 tmpFile = outFile 191 logWritingTo(outFile) 192 } else { 193 logWritingTo(inFile) 194 } 195 196 if f2, err = os.Create(tmpFile); err != nil { 197 f1.Close() 198 return err 199 } 200 201 defer func() { 202 if err != nil { 203 f2.Close() 204 f1.Close() 205 os.Remove(tmpFile) 206 return 207 } 208 if err = f2.Close(); err != nil { 209 return 210 } 211 if err = f1.Close(); err != nil { 212 return 213 } 214 if outFile == "" || inFile == outFile { 215 err = os.Rename(tmpFile, inFile) 216 } 217 }() 218 219 return ChangeUserPassword(f1, f2, pwOld, pwNew, conf) 220 } 221 222 // ChangeOwnerPassword reads a PDF stream from rs, changes the owner password and writes the encrypted PDF stream to w. 223 // A configuration containing the current passwords is required. 224 func ChangeOwnerPassword(rs io.ReadSeeker, w io.Writer, pwOld, pwNew string, conf *model.Configuration) error { 225 if rs == nil { 226 return errors.New("pdfcpu: ChangeOwnerPassword: missing rs") 227 } 228 229 if conf == nil { 230 return errors.New("pdfcpu: missing configuration for change owner password") 231 } 232 233 conf.Cmd = model.CHANGEOPW 234 conf.OwnerPW = pwOld 235 conf.OwnerPWNew = &pwNew 236 237 return Optimize(rs, w, conf) 238 } 239 240 // ChangeOwnerPasswordFile reads inFile, changes the owner password and writes the result to outFile. 241 // A configuration containing the current passwords is required. 242 func ChangeOwnerPasswordFile(inFile, outFile string, pwOld, pwNew string, conf *model.Configuration) (err error) { 243 if conf == nil { 244 return errors.New("pdfcpu: missing configuration for change owner password") 245 } 246 conf.Cmd = model.CHANGEOPW 247 conf.OwnerPW = pwOld 248 conf.OwnerPWNew = &pwNew 249 250 var f1, f2 *os.File 251 252 if f1, err = os.Open(inFile); err != nil { 253 return err 254 } 255 256 tmpFile := inFile + ".tmp" 257 if outFile != "" && inFile != outFile { 258 tmpFile = outFile 259 logWritingTo(outFile) 260 } else { 261 logWritingTo(inFile) 262 } 263 264 if f2, err = os.Create(tmpFile); err != nil { 265 return err 266 } 267 268 defer func() { 269 if err != nil { 270 f2.Close() 271 f1.Close() 272 os.Remove(tmpFile) 273 return 274 } 275 if err = f2.Close(); err != nil { 276 return 277 } 278 if err = f1.Close(); err != nil { 279 return 280 } 281 if outFile == "" || inFile == outFile { 282 err = os.Rename(tmpFile, inFile) 283 } 284 }() 285 286 return ChangeOwnerPassword(f1, f2, pwOld, pwNew, conf) 287 }