/* ====================================================================
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
contributor license agreements. See the NOTICE file distributed with
|
this work for additional information regarding copyright ownership.
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
(the "License"); you may not use this file except in compliance with
|
the License. You may obtain a copy of the License at
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
Unless required by applicable law or agreed to in writing, software
|
distributed under the License is distributed on an "AS IS" BASIS,
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
See the License for the specific language governing permissions and
|
limitations under the License.
|
==================================================================== */
|
|
|
using System;
|
using System.Collections.Generic;
|
using System.Text;
|
using System.Xml;
|
using System.IO;
|
using HH.WMS.Utils.NPOI.POIFS.FileSystem;
|
|
namespace HH.WMS.Utils.NPOI.POIFS.Crypt
|
{
|
public class EncryptionVerifier
|
{
|
private byte[] salt;
|
private byte[] verifier;
|
private byte[] verifierHash;
|
private byte[] encryptedKey;
|
private int verifierHashSize;
|
private int spinCount;
|
private int algorithm;
|
private int cipherMode;
|
|
public EncryptionVerifier(string descriptor)
|
{
|
XmlAttributeCollection keyData = null;
|
try
|
{
|
MemoryStream ms = new MemoryStream(Encoding.Default.GetBytes(descriptor));
|
XmlDocument xml = new XmlDocument();
|
xml.Load(ms);
|
XmlNodeList nodes = xml.GetElementsByTagName("keyEncryptor");
|
XmlNodeList keyEncryptor = nodes[0].ChildNodes;
|
|
for (int i = 0; i < keyEncryptor.Count; i++)
|
{
|
XmlNode node = keyEncryptor[i];
|
if (node.Name.Equals("p:encryptedKey"))
|
{
|
keyData = node.Attributes;
|
break;
|
}
|
}
|
|
if (keyData == null)
|
throw new EncryptedDocumentException("");
|
|
spinCount = Int32.Parse(keyData.GetNamedItem("spinCount").Value);
|
verifier = Convert.FromBase64String(keyData.GetNamedItem("encryptedVerifierHashInput").Value);
|
salt = Convert.FromBase64String(keyData.GetNamedItem("saltValue").Value);
|
encryptedKey = Convert.FromBase64String(keyData.GetNamedItem("encryptedKeyValue").Value);
|
|
int saltSize = Int32.Parse(keyData.GetNamedItem("saltSize").Value);
|
|
if (saltSize != salt.Length)
|
throw new EncryptedDocumentException("Invalid salt size");
|
|
verifierHash = Convert.FromBase64String(keyData.GetNamedItem("encryptedVerifierHashValue").Value);
|
|
int blockSize = Int32.Parse(keyData.GetNamedItem("blockSize").Value);
|
|
string alg = keyData.GetNamedItem("cipherAlgorithm").Value;
|
|
if ("AES".Equals(alg))
|
{
|
if (blockSize == 16)
|
algorithm = EncryptionHeader.ALGORITHM_AES_128;
|
else if (blockSize == 24)
|
algorithm = EncryptionHeader.ALGORITHM_AES_192;
|
else if (blockSize == 32)
|
algorithm = EncryptionHeader.ALGORITHM_AES_256;
|
else
|
throw new EncryptedDocumentException("Unsupported block size");
|
}
|
else
|
throw new EncryptedDocumentException("Unsupported cipher");
|
|
string chain = keyData.GetNamedItem("cipherChaining").Value;
|
|
if ("ChainingModeCBC".Equals(chain))
|
cipherMode = EncryptionHeader.MODE_CBC;
|
else if ("ChainingModeCFB".Equals(chain))
|
cipherMode = EncryptionHeader.MODE_CFB;
|
else
|
throw new EncryptedDocumentException("Unsupported chaining mode");
|
|
verifierHashSize = Int32.Parse(keyData.GetNamedItem("hashSize").Value);
|
|
}
|
catch
|
{
|
throw new EncryptedDocumentException("Unable to parse keyEncryptor");
|
}
|
}
|
|
public EncryptionVerifier(DocumentInputStream dis, int encryptedLength)
|
{
|
int saltSize = dis.ReadInt();
|
|
if (saltSize != 16)
|
throw new Exception("Salt size != 16 !?");
|
|
salt = new byte[16];
|
dis.ReadFully(salt);
|
verifier = new byte[16];
|
dis.ReadFully(verifier);
|
|
verifierHashSize = dis.ReadInt();
|
|
verifierHash = new byte[encryptedLength];
|
dis.ReadFully(verifierHash);
|
|
spinCount = 50000;
|
algorithm = EncryptionHeader.ALGORITHM_AES_128;
|
cipherMode = EncryptionHeader.MODE_ECB;
|
encryptedKey = null;
|
}
|
|
public byte[] Salt
|
{
|
get { return salt; }
|
}
|
|
public byte[] Verifier
|
{
|
get { return verifier; }
|
}
|
public byte[] VerifierHash
|
{
|
get
|
{
|
return verifierHash;
|
}
|
}
|
public int SpinCount
|
{
|
get { return spinCount; }
|
}
|
|
public int CipherMode
|
{
|
get { return cipherMode; }
|
}
|
|
public int Algorithm
|
{
|
get { return algorithm; }
|
}
|
|
public byte[] EncryptedKey
|
{
|
get { return encryptedKey; }
|
}
|
}
|
}
|