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  }