Exemplo n.º 1
0
        /// <summary>
        /// Sets the SDT content keeping permission elements.
        /// </summary>
        /// <param name="openXmlCompositeElement">The open XML composite element.</param>
        /// <param name="newChild">The new child.</param>
        private void SetSdtContentKeepingPermissionElements(OpenXmlCompositeElement openXmlCompositeElement, OpenXmlElement newChild)
        {
            PermStart start = openXmlCompositeElement.Descendants <PermStart>().FirstOrDefault();
            PermEnd   end   = openXmlCompositeElement.Descendants <PermEnd>().FirstOrDefault();

            openXmlCompositeElement.RemoveAllChildren();

            if (start != null)
            {
                openXmlCompositeElement.AppendChild(start);
            }

            openXmlCompositeElement.AppendChild(newChild);

            if (end != null)
            {
                openXmlCompositeElement.AppendChild(end);
            }
        }
Exemplo n.º 2
0
        private IEnumerable <OpenXmlElement> WrapText(TextBlock textBlock)
        {
            OpenXmlElement content;

            if (textBlock.Text == "\t")
            {
                content = new TabChar();
            }
            else
            {
                content = new Text(textBlock.Text);
            }

            var text = new Run(content);

            if (textBlock.Editable)
            {
                var id = _wordDocument.MainDocumentPart.Document.Descendants().OfType <PermStart>()
                         .Select(x => x.Id.Value)
                         .Union(new[] { 1 })
                         .Max();

                var permStart = new PermStart
                {
                    Id          = id,
                    EditorGroup = RangePermissionEditingGroupValues.Everyone
                };

                var permEnd = new PermEnd {
                    Id = id
                };

                return(new OpenXmlElement[] { permStart, text, permEnd });
            }

            return(new OpenXmlElement[] { text });
        }
Exemplo n.º 3
0
        private IEnumerable<OpenXmlElement> WrapText(TextBlock textBlock)
        {
            OpenXmlElement content;
            if (textBlock.Text == "\t") content = new TabChar();
            else content = new Text(textBlock.Text);

            var text = new Run(content);

            if (textBlock.Editable)
            {
                var id = _wordDocument.MainDocumentPart.Document.Descendants().OfType<PermStart>()
                    .Select(x => x.Id.Value)
                    .Union(new[] {1})
                    .Max();

                var permStart = new PermStart
                                    {
                                        Id = id,
                                        EditorGroup = RangePermissionEditingGroupValues.Everyone
                                    };

                var permEnd = new PermEnd {Id = id};

                return new OpenXmlElement[] {permStart, text, permEnd};
            }

            return new OpenXmlElement[] {text};
        }
Exemplo n.º 4
0
        // Main implementation
        private static void ApplyDocumentProtection(WordprocessingDocument wdDocument, string strPassword)
        {
            // Generate the Salt
            byte[] arrSalt             = new byte[16];
            RandomNumberGenerator rand = new RNGCryptoServiceProvider();

            rand.GetNonZeroBytes(arrSalt);

            //Array to hold Key Values
            byte[] generatedKey = new byte[4];

            //Maximum length of the password is 15 chars.
            int intMaxPasswordLength = 15;


            if (!String.IsNullOrEmpty(strPassword))
            {
                // Truncate the password to 15 characters
                strPassword = strPassword.Substring(0, Math.Min(strPassword.Length, intMaxPasswordLength));

                // Construct a new NULL-terminated string consisting of single-byte characters:
                //  -- > Get the single-byte values by iterating through the Unicode characters of the truncated Password.
                //   --> For each character, if the low byte is not equal to 0, take it. Otherwise, take the high byte.

                byte[] arrByteChars = new byte[strPassword.Length];

                for (int intLoop = 0; intLoop < strPassword.Length; intLoop++)
                {
                    int intTemp = Convert.ToInt32(strPassword[intLoop]);
                    arrByteChars[intLoop] = Convert.ToByte(intTemp & 0x00FF);
                    if (arrByteChars[intLoop] == 0)
                    {
                        arrByteChars[intLoop] = Convert.ToByte((intTemp & 0xFF00) >> 8);
                    }
                }

                // Compute the high-order word of the new key:

                // --> Initialize from the initial code array (see below), depending on the strPassword’s length.
                int intHighOrderWord = InitialCodeArray[arrByteChars.Length - 1];

                // --> For each character in the strPassword:
                //      --> For every bit in the character, starting with the least significant and progressing to (but excluding)
                //          the most significant, if the bit is set, XOR the key’s high-order word with the corresponding word from
                //          the Encryption Matrix

                for (int intLoop = 0; intLoop < arrByteChars.Length; intLoop++)
                {
                    int tmp = intMaxPasswordLength - arrByteChars.Length + intLoop;
                    for (int intBit = 0; intBit < 7; intBit++)
                    {
                        if ((arrByteChars[intLoop] & (0x0001 << intBit)) != 0)
                        {
                            intHighOrderWord ^= EncryptionMatrix[tmp, intBit];
                        }
                    }
                }

                // Compute the low-order word of the new key:

                // Initialize with 0
                int intLowOrderWord = 0;

                // For each character in the strPassword, going backwards
                for (int intLoopChar = arrByteChars.Length - 1; intLoopChar >= 0; intLoopChar--)
                {
                    // low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR character
                    intLowOrderWord = (((intLowOrderWord >> 14) & 0x0001) | ((intLowOrderWord << 1) & 0x7FFF)) ^ arrByteChars[intLoopChar];
                }

                // Lastly,low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR strPassword length XOR 0xCE4B.
                intLowOrderWord = (((intLowOrderWord >> 14) & 0x0001) | ((intLowOrderWord << 1) & 0x7FFF)) ^ arrByteChars.Length ^ 0xCE4B;

                // Combine the Low and High Order Word
                int intCombinedkey = (intHighOrderWord << 16) + intLowOrderWord;

                // The byte order of the result shall be reversed [Example: 0x64CEED7E becomes 7EEDCE64. end example],
                // and that value shall be hashed as defined by the attribute values.

                for (int intTemp = 0; intTemp < 4; intTemp++)
                {
                    generatedKey[intTemp] = Convert.ToByte(((uint)(intCombinedkey & (0x000000FF << (intTemp * 8)))) >> (intTemp * 8));
                }
            }

            // Implementation Notes List:
            // --> In this third stage, the reversed byte order legacy hash from the second stage shall be converted to Unicode hex
            // --> string representation
            StringBuilder sb = new StringBuilder();

            for (int intTemp = 0; intTemp < 4; intTemp++)
            {
                sb.Append(Convert.ToString(generatedKey[intTemp], 16));
            }
            generatedKey = Encoding.Unicode.GetBytes(sb.ToString().ToUpper());

            // Implementation Notes List:
            //Word appends the binary form of the salt attribute and not the base64 string representation when hashing
            // Before calculating the initial hash, you are supposed to prepend (not append) the salt to the key
            byte[] tmpArray1 = generatedKey;
            byte[] tmpArray2 = arrSalt;
            byte[] tempKey   = new byte[tmpArray1.Length + tmpArray2.Length];
            Buffer.BlockCopy(tmpArray2, 0, tempKey, 0, tmpArray2.Length);
            Buffer.BlockCopy(tmpArray1, 0, tempKey, tmpArray2.Length, tmpArray1.Length);
            generatedKey = tempKey;


            // Iterations specifies the number of times the hashing function shall be iteratively run (using each
            // iteration's result as the input for the next iteration).
            int iterations = 50000;

            // Implementation Notes List:
            //Word requires that the initial hash of the password with the salt not be considered in the count.
            //    The initial hash of salt + key is not included in the iteration count.
            HashAlgorithm sha1 = new SHA1Managed();

            generatedKey = sha1.ComputeHash(generatedKey);
            byte[] iterator = new byte[4];
            for (int intTmp = 0; intTmp < iterations; intTmp++)
            {
                //When iterating on the hash, you are supposed to append the current iteration number.
                iterator[0] = Convert.ToByte((intTmp & 0x000000FF) >> 0);
                iterator[1] = Convert.ToByte((intTmp & 0x0000FF00) >> 8);
                iterator[2] = Convert.ToByte((intTmp & 0x00FF0000) >> 16);
                iterator[3] = Convert.ToByte((intTmp & 0xFF000000) >> 24);

                generatedKey = concatByteArrays(iterator, generatedKey);
                generatedKey = sha1.ComputeHash(generatedKey);
            }

            // Apply the element
            DocumentProtection documentProtection = new DocumentProtection();

            documentProtection.Edit = DocumentProtectionValues.ReadOnly;

            OnOffValue docProtection = new OnOffValue(true);

            documentProtection.Enforcement = docProtection;

            documentProtection.CryptographicAlgorithmClass = CryptAlgorithmClassValues.Hash;
            documentProtection.CryptographicProviderType   = CryptProviderValues.RsaFull;
            documentProtection.CryptographicAlgorithmType  = CryptAlgorithmValues.TypeAny;
            documentProtection.CryptographicAlgorithmSid   = 4; // SHA1
            //    The iteration count is unsigned
            UInt32Value uintVal = new UInt32Value();

            uintVal.Value = (uint)iterations;
            documentProtection.CryptographicSpinCount = uintVal;
            documentProtection.Hash = Convert.ToBase64String(generatedKey);
            documentProtection.Salt = Convert.ToBase64String(arrSalt);

            // if protection in current document is exist then delete it
            DocumentProtection existingDocumentProtection = wdDocument.MainDocumentPart.DocumentSettingsPart.Settings.Descendants <DocumentProtection>().FirstOrDefault();

            if (existingDocumentProtection != null)
            {
                existingDocumentProtection.Remove();
            }

            wdDocument.MainDocumentPart.DocumentSettingsPart.Settings.AppendChild(documentProtection);
            wdDocument.MainDocumentPart.DocumentSettingsPart.Settings.Save();

            // add permission to edit

            int  id   = 1;
            Body body = wdDocument.MainDocumentPart.Document.GetFirstChild <Body>();

            // for all text
            foreach (var text in body.Descendants <Text>())
            {
                PermStart newPermStart = new PermStart();
                newPermStart.Id          = id;
                newPermStart.EditorGroup = RangePermissionEditingGroupValues.Everyone;
                text.InsertBeforeSelf(newPermStart);
                PermEnd newPermEnd = new PermEnd();
                newPermEnd.Id = id++;
                text.InsertAfterSelf(newPermEnd);
            }
            // for all table
//            var paras = body.Elements<Table>();
//
//            foreach (var para in paras)
//            {
//                PermStart newPermStart = new PermStart();
//                newPermStart.Id = id;
//                newPermStart.EditorGroup = RangePermissionEditingGroupValues.Everyone;
//                para.InsertBeforeSelf(newPermStart);
//                PermEnd newPermEnd = new PermEnd();
//                newPermEnd.Id = id++;
//                para.InsertAfterSelf(newPermEnd);
//            }
            wdDocument.MainDocumentPart.Document.Save();

            // for headers
            foreach (HeaderPart headerPart in wdDocument.MainDocumentPart.HeaderParts)
            {
                foreach (var text in headerPart.RootElement.Descendants <Text>())
                {
                    PermStart newPermStart = new PermStart();
                    newPermStart.Id          = id;
                    newPermStart.EditorGroup = RangePermissionEditingGroupValues.Everyone;
                    text.InsertBeforeSelf(newPermStart);
                    PermEnd newPermEnd = new PermEnd();
                    newPermEnd.Id = id++;
                    text.InsertAfterSelf(newPermEnd);
                }
                headerPart.Header.Save();
            }

            foreach (FooterPart footerPart in wdDocument.MainDocumentPart.FooterParts)
            {
                foreach (var text in footerPart.RootElement.Descendants <Text>())
                {
                    PermStart newPermStart = new PermStart();
                    newPermStart.Id          = id;
                    newPermStart.EditorGroup = RangePermissionEditingGroupValues.Everyone;
                    text.InsertBeforeSelf(newPermStart);
                    PermEnd newPermEnd = new PermEnd();
                    newPermEnd.Id = id++;
                    text.InsertAfterSelf(newPermEnd);
                }
                footerPart.Footer.Save();
            }
        }