Free cookie consent management tool by TermsFeed Policy Generator

source: branches/ProblemRefactoring/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/Encryption/EncryptionInfo.cs @ 13331

Last change on this file since 13331 was 12074, checked in by sraggl, 10 years ago

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 21.9 KB
Line 
1/*******************************************************************************
2 * You may amend and distribute as you like, but don't remove this header!
3 *
4 * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
5 * See http://www.codeplex.com/EPPlus for details.
6 *
7 * Copyright (C) 2011  Jan Källman
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
17 * See the GNU Lesser General Public License for more details.
18 *
19 * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
20 * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
21 *
22 * All code and executables are provided "as is" with no warranty either express or implied.
23 * The author accepts no liability for any damage or loss of business that this product may cause.
24 *
25 * Code change notes:
26 *
27 * Author             Change            Date
28 * ******************************************************************************
29 * Jan Källman        Added                   2013-01-05
30 *******************************************************************************/
31using System;
32using System.Collections.Generic;
33using System.IO;
34using System.Linq;
35using System.Text;
36using System.Xml;
37
38namespace OfficeOpenXml.Encryption
39{
40    internal abstract class EncryptionInfo
41    {
42        internal short MajorVersion;
43        internal short MinorVersion;
44        internal abstract void Read(byte[] data);
45
46        internal static EncryptionInfo ReadBinary(byte[] data)
47        {
48            var majorVersion = BitConverter.ToInt16(data, 0);
49            var minorVersion = BitConverter.ToInt16(data, 2);
50            EncryptionInfo ret;
51            if ((minorVersion == 2 || minorVersion == 3) && majorVersion <= 4) // minorVersion==1 is RC4, not supported.
52            {
53                ret = new EncryptionInfoBinary();
54            }
55            else if (majorVersion == 4 && minorVersion==4)
56            {
57                ret = new EncryptionInfoAgile();
58            }
59            else
60            {
61                throw (new NotSupportedException("Unsupported encryption format"));
62            }
63            ret.MajorVersion = majorVersion;
64            ret.MinorVersion = minorVersion;
65            ret.Read(data);
66            return ret;
67        }
68    }
69    internal enum eCipherAlgorithm
70    {
71        /// <summary>
72        /// AES. MUST conform to the AES algorithm.
73        /// </summary>
74        AES,
75        /// <summary>
76        /// RC2. MUST conform to [RFC2268].
77        /// </summary>
78        RC2,
79        /// <summary>
80        /// RC4.
81        /// </summary>
82        RC4,
83        /// <summary>
84        /// MUST conform to the DES algorithm.
85        /// </summary>
86        DES,
87        /// <summary>
88        /// MUST conform to the [DRAFT-DESX] algorithm.
89        /// </summary>
90        DESX,
91        /// <summary>
92        /// 3DES. MUST conform to the [RFC1851] algorithm.
93        /// </summary>
94        TRIPLE_DES,
95        /// 3DES_112 MUST conform to the [RFC1851] algorithm.
96        TRIPLE_DES_112       
97    }
98    internal enum eChainingMode
99    {
100        /// <summary>
101        /// Cipher block chaining (CBC).
102        /// </summary>
103        ChainingModeCBC,
104        /// <summary>
105        /// Cipher feedback chaining (CFB), with 8-bit window.
106        /// </summary>
107        ChainingModeCFB
108    }
109    /// <summary>
110    /// Hashalgorithm
111    /// </summary>
112    internal enum eHashAlogorithm
113    {
114        /// <summary>
115        /// Sha 1-MUST conform to [RFC4634]
116        /// </summary>
117        SHA1,
118        /// <summary>
119        /// Sha 256-MUST conform to [RFC4634]
120        /// </summary>
121        SHA256,
122        /// <summary>
123        /// Sha 384-MUST conform to [RFC4634]
124        /// </summary>
125        SHA384,
126        /// <summary>
127        /// Sha 512-MUST conform to [RFC4634]
128        /// </summary>
129        SHA512,
130        /// <summary>
131        /// MD5
132        /// </summary>
133        MD5,
134        /// <summary>
135        /// MD4
136        /// </summary>
137        MD4,
138        /// <summary>
139        /// MD2
140        /// </summary>
141        MD2,
142        /// <summary>
143        /// RIPEMD-128 MUST conform to [ISO/IEC 10118]
144        /// </summary>
145        RIPEMD128,
146        /// <summary>
147        /// RIPEMD-160 MUST conform to [ISO/IEC 10118]
148        /// </summary>
149        RIPEMD160,
150        /// <summary>
151        /// WHIRLPOOL MUST conform to [ISO/IEC 10118]
152        /// </summary>
153        WHIRLPOOL
154    }
155    /// <summary>
156    /// Handels the agile encryption
157    /// </summary>
158    internal class EncryptionInfoAgile : EncryptionInfo
159    {
160        XmlNamespaceManager _nsm;
161        public EncryptionInfoAgile()
162        {
163            var nt = new NameTable();
164            _nsm = new XmlNamespaceManager(nt);
165            _nsm.AddNamespace("d", "http://schemas.microsoft.com/office/2006/encryption");
166            _nsm.AddNamespace("c", "http://schemas.microsoft.com/office/2006/keyEncryptor/certificate");
167            _nsm.AddNamespace("p", "http://schemas.microsoft.com/office/2006/keyEncryptor/password");
168        }
169        internal class EncryptionKeyData : XmlHelper
170        {
171            public EncryptionKeyData(XmlNamespaceManager nsm, XmlNode topNode) :
172                base(nsm, topNode)
173            {
174
175            }
176            internal byte[] SaltValue
177            {
178                get
179                {
180                    var s = GetXmlNodeString("@saltValue");
181                    if (!string.IsNullOrEmpty(s))
182                    {
183                        return Convert.FromBase64String(s);
184                    }
185                    return null;
186                }
187                set
188                {
189                    SetXmlNodeString("@saltValue", Convert.ToBase64String(value));
190                }
191            }
192            internal eHashAlogorithm HashAlgorithm
193            {
194                get
195                {
196                    return GetHashAlgorithm(GetXmlNodeString("@hashAlgorithm"));
197                }
198                set
199                {
200                    SetXmlNodeString("@hashAlgorithm", GetHashAlgorithmString(value));
201                }
202            }
203
204            private eHashAlogorithm GetHashAlgorithm(string v)
205            {
206                switch (v)
207                {
208                    case "RIPEMD-128":
209                        return eHashAlogorithm.RIPEMD128;
210                    case "RIPEMD-160":
211                        return eHashAlogorithm.RIPEMD160;
212                    case "SHA-1":
213                        return eHashAlogorithm.SHA1;
214                    default:
215                        try
216                        {
217                            return (eHashAlogorithm)Enum.Parse(typeof(eHashAlogorithm),v);
218                        }
219                        catch
220                        {
221                            throw (new InvalidDataException("Invalid Hash algorithm"));
222                        }
223                }
224            }
225
226            private string GetHashAlgorithmString(eHashAlogorithm value)
227            {
228                switch (value)
229                {
230                    case eHashAlogorithm.RIPEMD128:
231                        return "RIPEMD-128";
232                    case eHashAlogorithm.RIPEMD160:
233                        return "RIPEMD-160";
234                    case eHashAlogorithm.SHA1:
235                        return "SHA-1";
236                    default:
237                        return value.ToString();
238                }
239            }
240            internal eChainingMode ChiptherChaining
241            {
242                get
243                {
244                    var v=GetXmlNodeString("@cipherChaining");
245                    try
246                    {
247                        return (eChainingMode)Enum.Parse(typeof(eChainingMode), v);
248                    }
249                    catch
250                    {
251                        throw (new InvalidDataException("Invalid chaining mode"));
252                    }
253                }
254                set
255                {
256                    SetXmlNodeString("@cipherChaining", value.ToString());
257                }
258            }
259            internal eCipherAlgorithm CipherAlgorithm
260            {
261                get
262                {
263                    return GetCipherAlgorithm(GetXmlNodeString("@cipherAlgorithm"));
264                }
265                set
266                {
267                    SetXmlNodeString("@cipherAlgorithm", GetCipherAlgorithmString(value));
268                }
269            }
270
271            private eCipherAlgorithm GetCipherAlgorithm(string v)
272            {
273                switch (v)
274                {
275                    case "3DES":
276                        return eCipherAlgorithm.TRIPLE_DES;
277                    case "3DES_112":
278                        return eCipherAlgorithm.TRIPLE_DES_112;
279                    default:
280                        try
281                        {
282                            return (eCipherAlgorithm)Enum.Parse(typeof(eCipherAlgorithm), v);
283                        }
284                        catch
285                        {
286                            throw (new InvalidDataException("Invalid Hash algorithm"));
287                        }
288                }
289            }
290
291            private string GetCipherAlgorithmString(eCipherAlgorithm alg)
292            {
293                switch (alg)
294                {
295                    case eCipherAlgorithm.TRIPLE_DES:
296                        return "3DES";
297                    case eCipherAlgorithm.TRIPLE_DES_112:
298                        return "3DES_112";                   
299                    default:
300                        return alg.ToString();
301                }
302            }
303            internal int HashSize
304            {
305                get
306                {
307                    return GetXmlNodeInt("@hashSize");
308                }
309                set
310                {
311                    SetXmlNodeString("@hashSize", value.ToString());
312                }
313            }
314            internal int KeyBits
315            {
316                get
317                {
318                    return GetXmlNodeInt("@keyBits");
319                }
320                set
321                {
322                    SetXmlNodeString("@keyBits", value.ToString());
323                }
324            }
325            internal int BlockSize
326            {
327                get
328                {
329                    return GetXmlNodeInt("@blockSize");
330                }
331                set
332                {
333                    SetXmlNodeString("@blockSize", value.ToString());
334                }
335            }
336            internal int SaltSize
337            {
338                get
339                {
340                    return GetXmlNodeInt("@saltSize");
341                }
342                set
343                {
344                    SetXmlNodeString("@saltSize", value.ToString());
345                }
346            }
347        }
348        internal class EncryptionDataIntegrity : XmlHelper
349        {
350            public EncryptionDataIntegrity(XmlNamespaceManager nsm, XmlNode topNode) :
351                base(nsm, topNode)
352            {
353
354            }
355            internal byte[] EncryptedHmacValue
356            {
357                get
358                {
359                    var s = GetXmlNodeString("@encryptedHmacValue");
360                    if (!string.IsNullOrEmpty(s))
361                    {
362                        return Convert.FromBase64String(s);
363                    }
364                    return null;
365                }
366                set
367                {
368                    SetXmlNodeString("@encryptedHmacValue", Convert.ToBase64String(value));
369                }
370            }
371            internal byte[] EncryptedHmacKey
372            {
373                get
374                {
375                    var s = GetXmlNodeString("@encryptedHmacKey");
376                    if (!string.IsNullOrEmpty(s))
377                    {
378                        return Convert.FromBase64String(s);
379                    }
380                    return null;
381                }
382                set
383                {
384                    SetXmlNodeString("@encryptedHmacKey", Convert.ToBase64String(value));
385                }
386            }
387        }
388        internal class EncryptionKeyEncryptor : EncryptionKeyData
389        {
390            public EncryptionKeyEncryptor(XmlNamespaceManager nsm, XmlNode topNode) :
391                base(nsm, topNode)
392            {
393
394            }
395            internal byte[] EncryptedKeyValue
396            {
397                get
398                {
399                    var s = GetXmlNodeString("@encryptedKeyValue");
400                    if (!string.IsNullOrEmpty(s))
401                    {
402                        return Convert.FromBase64String(s);
403                    }
404                    return null;
405                }
406                set
407                {
408                    SetXmlNodeString("@encryptedKeyValue", Convert.ToBase64String(value));
409                }
410            }
411            internal byte[] EncryptedVerifierHash
412            {
413                get
414                {
415                    var s = GetXmlNodeString("@encryptedVerifierHashValue");
416                    if (!string.IsNullOrEmpty(s))
417                    {
418                        return Convert.FromBase64String(s);
419                    }
420                    return null;
421
422                }
423                set
424                {
425                    SetXmlNodeString("@encryptedVerifierHashValue", Convert.ToBase64String(value));
426                }
427            }
428            internal byte[] EncryptedVerifierHashInput
429            {
430                get
431                {
432                    var s = GetXmlNodeString("@encryptedVerifierHashInput");
433                    if (!string.IsNullOrEmpty(s))
434                    {
435                        return Convert.FromBase64String(s);
436                    }
437                    return null;
438                }
439                set
440                {
441                    SetXmlNodeString("@encryptedVerifierHashInput", Convert.ToBase64String(value));
442                }
443            }
444            internal byte[] VerifierHashInput { get; set; }
445            internal byte[] VerifierHash { get; set; }
446            internal byte[] KeyValue { get; set; }
447            internal int SpinCount
448            {
449                get
450                {
451                    return GetXmlNodeInt("@spinCount");
452                }
453                set
454                {
455                    SetXmlNodeString("@spinCount", value.ToString());
456                }
457            }
458        }
459        /*
460        <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
461           <encryption xmlns="http://schemas.microsoft.com/office/2006/encryption" xmlns:p="http://schemas.microsoft.com/office/2006/keyEncryptor/password" xmlns:c="http://schemas.microsoft.com/office/2006/keyEncryptor/certificate">
462               <keyData saltSize="16" blockSize="16" keyBits="256" hashSize="64" cipherAlgorithm="AES" cipherChaining="ChainingModeCBC" hashAlgorithm="SHA512" saltValue="pa+hrJ3s1zrY6hmVuSa5JQ==" />
463               <dataIntegrity encryptedHmacKey="nd8i4sEKjsMjVN2gLo91oFN2e7bhMpWKDCAUBEpz4GW6NcE3hBXDobLksZvQGwLrPj0SUVzQA8VuDMyjMAfVCA==" encryptedHmacValue="O6oegHpQVz2uO7Om4oZijSi4kzLiiMZGIjfZlq/EFFO6PZbKitenBqe2or1REaxaI7gO/JmtJzZ1ViucqTaw4g==" />
464               <keyEncryptors>
465                   <keyEncryptor uri="http://schemas.microsoft.com/office/2006/keyEncryptor/password">
466                      <p:encryptedKey spinCount="100000" saltSize="16" blockSize="16" keyBits="256" hashSize="64" cipherAlgorithm="AES" cipherChaining="ChainingModeCBC" hashAlgorithm="SHA512" saltValue="u2BNFAuHYn3M/WRja3/uPg==" encryptedVerifierHashInput="M0V+fRolJMRgFyI9w+AVxQ==" encryptedVerifierHashValue="V/6l9pFH7AaXFqEbsnFBfHe7gMOqFeRwaNMjc7D3LNdw6KgZzOOQlt5sE8/oG7GPVBDGfoQMTxjQydVPVy4qng==" encryptedKeyValue="B0/rbSQRiIKG5CQDH6AKYSybdXzxgKAfX1f+S5k7mNE=" />
467                   </keyEncryptor></keyEncryptors></encryption>
468        */
469       
470        /***
471         * <?xml version="1.0" encoding="UTF-8" standalone="true"?>
472            <encryption xmlns:c="http://schemas.microsoft.com/office/2006/keyEncryptor/certificate" xmlns:p="http://schemas.microsoft.com/office/2006/keyEncryptor/password" xmlns="http://schemas.microsoft.com/office/2006/encryption">
473         *      <keyData saltValue="XmTB/XBGJSbwd/GTKzQv5A==" hashAlgorithm="SHA512" cipherChaining="ChainingModeCBC" cipherAlgorithm="AES" hashSize="64" keyBits="256" blockSize="16" saltSize="16"/>
474         *      <dataIntegrity encryptedHmacValue="WWw3Bb2dbcNPMnl9f1o7rO0u7sclWGKTXqBA6rRzKsP2KzWS5T0LxY9qFoC6QE67t/t+FNNtMDdMtE3D1xvT8w==" encryptedHmacKey="p/dVdlJY5Kj0k3jI1HRjqtk4s0Y4HmDAsc8nqZgfxNS7DopAsS3LU/2p3CYoIRObHsnHTAtbueH08DFCYGZURg=="/>
475         *          <keyEncryptors>
476         *              <keyEncryptor uri="http://schemas.microsoft.com/office/2006/keyEncryptor/password">
477         *                  <p:encryptedKey saltValue="EeBtY0QftyOkLztCl7NF0g==" hashAlgorithm="SHA512" cipherChaining="ChainingModeCBC" cipherAlgorithm="AES" hashSize="64" keyBits="256" blockSize="16" saltSize="16" encryptedKeyValue="Z7AO8vHnnPZEb1VqyZLJ6JFc3Mq3E322XPxWXS21fbU=" encryptedVerifierHashValue="G7BxbKnZanldvtsbu51mP9J3f9Wr5vCfCpvWSh5eIJff7Sr3J2DzH1/9aKj9uIpqFQIsLohpRk+oBYDcX7hRgw==" encryptedVerifierHashInput="851eszl5y5rdU1RnTjEWHw==" spinCount="100000"/>
478         *              </keyEncryptor>
479         *      </keyEncryptors>
480         *      </encryption
481         * ***/
482        internal EncryptionDataIntegrity DataIntegrity { get; set; }
483        internal EncryptionKeyData KeyData { get; set; }
484        internal List<EncryptionKeyEncryptor> KeyEncryptors
485        {
486            get;
487            private set;
488        }
489
490        internal XmlDocument Xml {get;set;}
491        internal override void Read(byte[] data)
492        {
493            var byXml = new byte[data.Length - 8];
494            Array.Copy(data, 8, byXml, 0, data.Length - 8);
495            var xml = Encoding.UTF8.GetString(byXml);
496            ReadFromXml(xml);
497        }
498        internal void ReadFromXml(string xml)
499        {
500            Xml = new XmlDocument();
501            XmlHelper.LoadXmlSafe(Xml, xml, Encoding.UTF8);
502            var node = Xml.SelectSingleNode("/d:encryption/d:keyData", _nsm);
503            KeyData = new EncryptionKeyData(_nsm, node);
504            node = Xml.SelectSingleNode("/d:encryption/d:dataIntegrity", _nsm);
505            DataIntegrity = new EncryptionDataIntegrity(_nsm, node);
506            KeyEncryptors = new List<EncryptionKeyEncryptor>();
507
508            var list = Xml.SelectNodes("/d:encryption/d:keyEncryptors/d:keyEncryptor/p:encryptedKey", _nsm);
509            if (list != null)
510            {
511                foreach (XmlNode n in list)
512                {
513                    KeyEncryptors.Add(new EncryptionKeyEncryptor(_nsm, n));
514                }
515            }
516
517        }
518    }
519    /// <summary>
520    /// Handles the EncryptionInfo stream
521    /// </summary>
522    internal class EncryptionInfoBinary : EncryptionInfo
523    {
524
525
526        internal Flags Flags;
527        internal uint HeaderSize;
528        internal EncryptionHeader Header;
529        internal EncryptionVerifier Verifier;
530        internal override void Read(byte[] data)
531        {
532            Flags = (Flags)BitConverter.ToInt32(data, 4);
533            HeaderSize = (uint)BitConverter.ToInt32(data, 8);
534
535            /**** EncryptionHeader ****/
536            Header = new EncryptionHeader();
537            Header.Flags = (Flags)BitConverter.ToInt32(data, 12);
538            Header.SizeExtra = BitConverter.ToInt32(data, 16);
539            Header.AlgID = (AlgorithmID)BitConverter.ToInt32(data, 20);
540            Header.AlgIDHash = (AlgorithmHashID)BitConverter.ToInt32(data, 24);
541            Header.KeySize = BitConverter.ToInt32(data, 28);
542            Header.ProviderType = (ProviderType)BitConverter.ToInt32(data, 32);
543            Header.Reserved1 = BitConverter.ToInt32(data, 36);
544            Header.Reserved2 = BitConverter.ToInt32(data, 40);
545
546            byte[] text = new byte[(int)HeaderSize - 34];
547            Array.Copy(data, 44, text, 0, (int)HeaderSize - 34);
548            Header.CSPName = UTF8Encoding.Unicode.GetString(text);
549
550            int pos = (int)HeaderSize + 12;
551
552            /**** EncryptionVerifier ****/
553            Verifier = new EncryptionVerifier();
554            Verifier.SaltSize = (uint)BitConverter.ToInt32(data, pos);
555            Verifier.Salt = new byte[Verifier.SaltSize];
556
557            Array.Copy(data, pos + 4, Verifier.Salt, 0, Verifier.SaltSize);
558
559            Verifier.EncryptedVerifier = new byte[16];
560            Array.Copy(data, pos + 20, Verifier.EncryptedVerifier, 0, 16);
561
562            Verifier.VerifierHashSize = (uint)BitConverter.ToInt32(data, pos + 36);
563            Verifier.EncryptedVerifierHash = new byte[Verifier.VerifierHashSize];
564            Array.Copy(data, pos + 40, Verifier.EncryptedVerifierHash, 0, Verifier.VerifierHashSize);
565        }
566        internal byte[] WriteBinary()
567        {
568            MemoryStream ms = new MemoryStream();
569            BinaryWriter bw = new BinaryWriter(ms);
570
571            bw.Write(MajorVersion);
572            bw.Write(MinorVersion);
573            bw.Write((int)Flags);
574            byte[] header = Header.WriteBinary();
575            bw.Write((uint)header.Length);
576            bw.Write(header);
577            bw.Write(Verifier.WriteBinary());
578
579            bw.Flush();
580            return ms.ToArray();
581        }
582
583    }
584}
Note: See TracBrowser for help on using the repository browser.