Ejemplo n.º 1
0
 virtual public bool ReadKey(PdfDictionary enc, byte[] password) {
     if (password == null)
         password = new byte[0];
     byte[] oValue = DocWriter.GetISOBytes(enc.Get(PdfName.O).ToString());
     byte[] uValue = DocWriter.GetISOBytes(enc.Get(PdfName.U).ToString());
     byte[] oeValue = DocWriter.GetISOBytes(enc.Get(PdfName.OE).ToString());
     byte[] ueValue = DocWriter.GetISOBytes(enc.Get(PdfName.UE).ToString());
     byte[] perms = DocWriter.GetISOBytes(enc.Get(PdfName.PERMS).ToString());
     bool isUserPass = false;
     IDigest md = DigestUtilities.GetDigest("SHA-256");
     md.BlockUpdate(password, 0, Math.Min(password.Length, 127));
     md.BlockUpdate(oValue, VALIDATION_SALT_OFFSET, SALT_LENGHT);
     md.BlockUpdate(uValue, 0, OU_LENGHT);
     byte[] hash = DigestUtilities.DoFinal(md);
     bool isOwnerPass = CompareArray(hash, oValue, 32);
     AESCipherCBCnoPad ac;
     if (isOwnerPass) {
         md.BlockUpdate(password, 0, Math.Min(password.Length, 127));
         md.BlockUpdate(oValue, KEY_SALT_OFFSET, SALT_LENGHT);
         md.BlockUpdate(uValue, 0, OU_LENGHT);
         md.DoFinal(hash, 0);
         ac = new AESCipherCBCnoPad(false, hash);
         key = ac.ProcessBlock(oeValue, 0, oeValue.Length);
     }
     else {
         md.BlockUpdate(password, 0, Math.Min(password.Length, 127));
         md.BlockUpdate(uValue, VALIDATION_SALT_OFFSET, SALT_LENGHT);
         md.DoFinal(hash, 0);
         isUserPass = CompareArray(hash, uValue, 32);
         if (!isUserPass)
             throw new BadPasswordException(MessageLocalization.GetComposedMessage("bad.user.password"));
         md.BlockUpdate(password, 0, Math.Min(password.Length, 127));
         md.BlockUpdate(uValue, KEY_SALT_OFFSET, SALT_LENGHT);
         md.DoFinal(hash, 0);
         ac = new AESCipherCBCnoPad(false, hash);
         key = ac.ProcessBlock(ueValue, 0, ueValue.Length);
     }
     ac = new AESCipherCBCnoPad(false, key);
     byte[] decPerms = ac.ProcessBlock(perms, 0, perms.Length);
     if (decPerms[9] != (byte)'a' || decPerms[10] != (byte)'d' || decPerms[11] != (byte)'b')
         throw new BadPasswordException(MessageLocalization.GetComposedMessage("bad.user.password"));
     permissions = (decPerms[0] & 0xff) | ((decPerms[1] & 0xff) << 8)
             | ((decPerms[2] & 0xff) << 16) | ((decPerms[2] & 0xff) << 24);
     encryptMetadata = decPerms[8] == (byte)'T';
     return isOwnerPass;
 }
Ejemplo n.º 2
0
    // gets keylength and revision and uses revison to choose the initial values for permissions
    virtual public void SetupAllKeys(byte[] userPassword, byte[] ownerPassword, int permissions) {
        if (ownerPassword == null || ownerPassword.Length == 0)
            ownerPassword = DigestAlgorithms.Digest("MD5", CreateDocumentId());
        md5.Reset();
        permissions |= (int)((revision == STANDARD_ENCRYPTION_128 || revision == AES_128 || revision == AES_256) ? (uint)0xfffff0c0 : (uint)0xffffffc0);
        permissions &= unchecked((int)0xfffffffc);
        this.permissions = permissions;
        if (revision == AES_256) {
            if (userPassword == null)
                userPassword = new byte[0];
            documentID = CreateDocumentId();
            byte[] uvs = IVGenerator.GetIV(8);
            byte[] uks = IVGenerator.GetIV(8);
            key = IVGenerator.GetIV(32);
            // Algorithm 3.8.1
            IDigest md = DigestUtilities.GetDigest("SHA-256");
            md.BlockUpdate(userPassword, 0, Math.Min(userPassword.Length, 127));
            md.BlockUpdate(uvs, 0, uvs.Length);
            userKey = new byte[48];
            md.DoFinal(userKey, 0);
            System.Array.Copy(uvs, 0, userKey, 32, 8);
            System.Array.Copy(uks, 0, userKey, 40, 8);
            // Algorithm 3.8.2
            md.BlockUpdate(userPassword, 0, Math.Min(userPassword.Length, 127));
            md.BlockUpdate(uks, 0, uks.Length);
            byte[] tempDigest = new byte[32];
            md.DoFinal(tempDigest, 0);
            AESCipherCBCnoPad ac = new AESCipherCBCnoPad(true, tempDigest);
            ueKey = ac.ProcessBlock(key, 0, key.Length);
            // Algorithm 3.9.1
            byte[] ovs = IVGenerator.GetIV(8);
            byte[] oks = IVGenerator.GetIV(8);
            md.BlockUpdate(ownerPassword, 0, Math.Min(ownerPassword.Length, 127));
            md.BlockUpdate(ovs, 0, ovs.Length);
            md.BlockUpdate(userKey, 0, userKey.Length);
            ownerKey = new byte[48];
            md.DoFinal(ownerKey, 0);
            System.Array.Copy(ovs, 0, ownerKey, 32, 8);
            System.Array.Copy(oks, 0, ownerKey, 40, 8);
            // Algorithm 3.9.2
            md.BlockUpdate(ownerPassword, 0, Math.Min(ownerPassword.Length, 127));
            md.BlockUpdate(oks, 0, oks.Length);
            md.BlockUpdate(userKey, 0, userKey.Length);
            md.DoFinal(tempDigest, 0);
            ac = new AESCipherCBCnoPad(true, tempDigest);
            oeKey = ac.ProcessBlock(key, 0, key.Length);
            // Algorithm 3.10
            byte[] permsp = IVGenerator.GetIV(16);
            permsp[0] = (byte)permissions;
            permsp[1] = (byte)(permissions >> 8);
            permsp[2] = (byte)(permissions >> 16);
            permsp[3] = (byte)(permissions >> 24);
            permsp[4] = (byte)(255);
            permsp[5] = (byte)(255);
            permsp[6] = (byte)(255);
            permsp[7] = (byte)(255);
            permsp[8] = encryptMetadata ? (byte)'T' : (byte)'F';
            permsp[9] = (byte)'a';
            permsp[10] = (byte)'d';
            permsp[11] = (byte)'b';
            ac = new AESCipherCBCnoPad(true, key);
            perms = ac.ProcessBlock(permsp, 0, permsp.Length);
        }
        else {
            //PDF refrence 3.5.2 Standard Security Handler, Algorithum 3.3-1
            //If there is no owner password, use the user password instead.
            byte[] userPad = PadPassword(userPassword);
            byte[] ownerPad = PadPassword(ownerPassword);

            this.ownerKey = ComputeOwnerKey(userPad, ownerPad);
            documentID = CreateDocumentId();
            SetupByUserPad(this.documentID, userPad, this.ownerKey, permissions);
        }
    }