public ProcessBlock ( byte inp, int inpOff, int inpLen ) : byte[] | ||
inp | byte | |
inpOff | int | |
inpLen | int | |
return | byte[] |
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; }
// 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); } }