Example #1
0
 public static void SetPassword(CT_SheetProtection xobj, String password, HashAlgorithm hashAlgo, String prefix)
 {
     if (password == null)
     {
         xobj.password      = null;
         xobj.algorithmName = null;
         xobj.hashValue     = null;
         xobj.saltValue     = null;
         xobj.spinCount     = null;
         return;
     }
     if (hashAlgo == null)
     {
         int hash = CryptoFunctions.CreateXorVerifier1(password);
         xobj.password = String.Format("{0:X4}", hash).ToUpper();
     }
     else
     {
         SecureRandom random    = new SecureRandom();
         byte[]       salt      = random.GenerateSeed(16);
         int          spinCount = 100000;
         byte[]       hash      = CryptoFunctions.HashPassword(password, hashAlgo, salt, spinCount, false);
         xobj.algorithmName = hashAlgo.jceId;
         xobj.hashValue     = Convert.ToBase64String(hash);
         xobj.saltValue     = Convert.ToBase64String(salt);
         xobj.spinCount     = "" + spinCount;
     }
 }
Example #2
0
        public static bool ValidatePassword(CT_SheetProtection xobj, String password, String prefix)
        {
            if (password == null)
            {
                return(false);
            }

            string xorHashVal = xobj.password;
            string algoName   = xobj.algorithmName;
            string hashVal    = xobj.hashValue;
            string saltVal    = xobj.saltValue;
            string spinCount  = xobj.spinCount;

            if (xorHashVal != null)
            {
                int hash1 = Int32.Parse(xorHashVal, NumberStyles.HexNumber);
                int hash2 = CryptoFunctions.CreateXorVerifier1(password);
                return(hash1 == hash2);
            }
            else
            {
                if (hashVal == null || algoName == null || saltVal == null || spinCount == null)
                {
                    return(false);
                }

                byte[]        hash1    = Convert.FromBase64String(hashVal);
                HashAlgorithm hashAlgo = HashAlgorithm.FromString(algoName);
                byte[]        salt     = Convert.FromBase64String(saltVal);
                int           spinCnt  = Int32.Parse(spinCount);
                byte[]        hash2    = CryptoFunctions.HashPassword(password, hashAlgo, salt, spinCnt, false);
                return(Arrays.Equals(hash1, hash2));
            }
        }
Example #3
0
        /**
         * Validates the password, i.e.
         * calculates the hash of the given password and Compares it against the stored hash
         *
         * @param xobj the xmlbeans object which Contains the password attributes
         * @param password the password, if null the method will always return false,
         *  even if there's no password Set
         * @param prefix the prefix of the password attributes, may be null
         *
         * @return true, if the hashes match
         */
        public static bool ValidatePassword(XmlNode xobj, String password, String prefix)
        {
            // TODO: is "velvetSweatshop" the default password?
            if (password == null)
            {
                return(false);
            }

            XPathNavigator cur = xobj.CreateNavigator();

            cur.MoveToAttribute("password", prefix);
            String xorHashVal = cur.Value;

            cur.MoveToAttribute("algorithmName", prefix);
            String algoName = cur.Value;

            cur.MoveToAttribute("hashValue", prefix);
            String hashVal = cur.Value;

            cur.MoveToAttribute("saltValue", prefix);
            String saltVal = cur.Value;

            cur.MoveToAttribute("spinCount", prefix);
            String spinCount = cur.Value;

            //cur.Dispose();

            if (xorHashVal != null)
            {
                int hash1 = Int32.Parse(xorHashVal, NumberStyles.HexNumber);
                int hash2 = CryptoFunctions.CreateXorVerifier1(password);
                return(hash1 == hash2);
            }
            else
            {
                if (hashVal == null || algoName == null || saltVal == null || spinCount == null)
                {
                    return(false);
                }

                byte[]        hash1    = Convert.FromBase64String(hashVal);
                HashAlgorithm hashAlgo = HashAlgorithm.FromString(algoName);
                byte[]        salt     = Convert.FromBase64String(saltVal);
                int           spinCnt  = Int32.Parse(spinCount);
                byte[]        hash2    = CryptoFunctions.HashPassword(password, hashAlgo, salt, spinCnt, false);
                return(Arrays.Equals(hash1, hash2));
            }
        }
Example #4
0
        protected internal static ISecretKey GenerateSecretKey(string password, EncryptionVerifier ver, int keySize)
        {
            HashAlgorithm hashAlgo = ver.HashAlgorithm;

            byte[] pwHash = CryptoFunctions.HashPassword(password, hashAlgo, ver.Salt, ver.SpinCount);

            byte[] blockKey = new byte[4];
            LittleEndian.PutInt(blockKey, 0, 0);

            byte[] finalHash = CryptoFunctions.GenerateKey(pwHash, hashAlgo, blockKey, hashAlgo.hashSize);
            byte[] x1        = FillAndXor(finalHash, (byte)0x36);
            byte[] x2        = FillAndXor(finalHash, (byte)0x5c);

            byte[] x3 = new byte[x1.Length + x2.Length];
            Array.Copy(x1, 0, x3, 0, x1.Length);
            Array.Copy(x2, 0, x3, x1.Length, x2.Length);

            byte[] key = Arrays.CopyOf(x3, keySize);

            ISecretKey skey = new SecretKeySpec(key, ver.CipherAlgorithm.jceId);

            return(skey);
        }
Example #5
0
        /**
         * Sets the XORed or hashed password
         *
         * @param xobj the xmlbeans object which Contains the password attributes
         * @param password the password, if null, the password attributes will be Removed
         * @param hashAlgo the hash algorithm, if null the password will be XORed
         * @param prefix the prefix of the password attributes, may be null
         */
        public static void SetPassword(XmlNode xobj, String password, HashAlgorithm hashAlgo, String prefix)
        {
            XPathNavigator cur = xobj.CreateNavigator();

            if (password == null)
            {
                //dose the prefix is namespace? check it!!!
                if (cur.MoveToAttribute("password", prefix))
                {
                    cur.DeleteSelf();
                }
                if (cur.MoveToAttribute("algorithmName", prefix))
                {
                    cur.DeleteSelf();
                }
                if (cur.MoveToAttribute("hashValue", prefix))
                {
                    cur.DeleteSelf();
                }
                if (cur.MoveToAttribute("saltValue", prefix))
                {
                    cur.DeleteSelf();
                }
                if (cur.MoveToAttribute("spinCount", prefix))
                {
                    cur.DeleteSelf();
                }
                return;
            }

            //cur.ToFirstContentToken();
            if (hashAlgo == null)
            {
                int hash = CryptoFunctions.CreateXorVerifier1(password);
                cur.CreateAttribute(prefix, "password", null, String.Format("{0:X4}", hash).ToUpper());
                //cur.InsertAttributeWithValue(GetAttrName(prefix, "password"),
                //                             String.Format("{0:X}", hash).ToUpper());
            }
            else
            {
                SecureRandom random = new SecureRandom();
                byte[]       salt   = random.GenerateSeed(16);

                // 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 spinCount = 100000;

                // 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
                byte[] hash = CryptoFunctions.HashPassword(password, hashAlgo, salt, spinCount, false);
                cur.CreateAttribute(prefix, "algorithmName", null, hashAlgo.jceId);
                cur.CreateAttribute(prefix, "hashValue", null, Convert.ToBase64String(hash));
                cur.CreateAttribute(prefix, "saltValue", null, Convert.ToBase64String(salt));
                cur.CreateAttribute(prefix, "spinCount", null, "" + spinCount);
                //cur.InsertAttributeWithValue(GetAttrName(prefix, "algorithmName"), hashAlgo.jceId);
                //cur.InsertAttributeWithValue(GetAttrName(prefix, "hashValue"), Convert.ToBase64String(hash));
                //cur.InsertAttributeWithValue(GetAttrName(prefix, "saltValue"), Convert.ToBase64String(salt));
                //cur.InsertAttributeWithValue(GetAttrName(prefix, "spinCount"), "" + spinCount);
            }
            //cur.Dispose();
        }
Example #6
0
        /**
         * Set decryption password
         */
        public override bool VerifyPassword(String password)
        {
            AgileEncryptionVerifier ver        = (AgileEncryptionVerifier)builder.GetVerifier();
            AgileEncryptionHeader   header     = (AgileEncryptionHeader)builder.GetHeader();
            HashAlgorithm           hashAlgo   = header.HashAlgorithm;
            CipherAlgorithm         cipherAlgo = header.CipherAlgorithm;
            int blockSize = header.BlockSize;
            int keySize   = header.KeySize / 8;

            byte[] pwHash = CryptoFunctions.HashPassword(password, ver.HashAlgorithm, ver.Salt, ver.SpinCount);

            /**
             * encryptedVerifierHashInput: This attribute MUST be generated by using the following steps:
             * 1. Generate a random array of bytes with the number of bytes used specified by the saltSize
             *    attribute.
             * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
             *    the binary byte array used to create the saltValue attribute, and a blockKey byte array
             *    consisting of the following bytes: 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, and 0x79.
             * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
             *    attribute as an Initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
             *    integral multiple of blockSize bytes, pad the array with 0x00 to the next integral multiple of
             *    blockSize bytes.
             * 4. Use base64 to encode the result of step 3.
             */
            byte[] verfierInputEnc = hashInput(builder, pwHash, kVerifierInputBlock, ver.EncryptedVerifier, Cipher.DECRYPT_MODE);
            SetVerifier(verfierInputEnc);
            MessageDigest hashMD = CryptoFunctions.GetMessageDigest(hashAlgo);

            byte[] verifierHash = hashMD.Digest(verfierInputEnc);

            /**
             * encryptedVerifierHashValue: This attribute MUST be generated by using the following steps:
             * 1. Obtain the hash value of the random array of bytes generated in step 1 of the steps for
             *    encryptedVerifierHashInput.
             * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
             *    the binary byte array used to create the saltValue attribute, and a blockKey byte array
             *    consisting of the following bytes: 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, and 0x4e.
             * 3. Encrypt the hash value obtained in step 1 by using the binary form of the saltValue attribute as
             *    an Initialization vector as specified in section 2.3.4.12. If hashSize is not an integral multiple of
             *    blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes.
             * 4. Use base64 to encode the result of step 3.
             */
            byte[] verifierHashDec = hashInput(builder, pwHash, kHashedVerifierBlock, ver.EncryptedVerifierHash, Cipher.DECRYPT_MODE);
            verifierHashDec = CryptoFunctions.GetBlock0(verifierHashDec, hashAlgo.hashSize);

            /**
             * encryptedKeyValue: This attribute MUST be generated by using the following steps:
             * 1. Generate a random array of bytes that is the same size as specified by the
             *    Encryptor.KeyData.keyBits attribute of the parent element.
             * 2. Generate an encryption key as specified in section 2.3.4.11, using the user-supplied password,
             *    the binary byte array used to create the saltValue attribute, and a blockKey byte array
             *    consisting of the following bytes: 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, and 0xd6.
             * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
             *    attribute as an Initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
             *    integral multiple of blockSize bytes, pad the array with 0x00 to an integral multiple of
             *    blockSize bytes.
             * 4. Use base64 to encode the result of step 3.
             */
            byte[] keyspec = hashInput(builder, pwHash, kCryptoKeyBlock, ver.EncryptedKey, Cipher.DECRYPT_MODE);
            keyspec = CryptoFunctions.GetBlock0(keyspec, keySize);
            SecretKeySpec secretKey = new SecretKeySpec(keyspec, ver.CipherAlgorithm.jceId);

            /**
             * 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor
             *    Contained within the KeyEncryptors sequence. Use this key for encryption operations in the
             *    remaining steps of this section.
             * 2. Generate a random array of bytes, known as Salt, of the same length as the value of the
             *    KeyData.HashSize attribute.
             * 3. Encrypt the random array of bytes generated in step 2 by using the binary form of the
             *    KeyData.saltValue attribute and a blockKey byte array consisting of the following bytes: 0x5f,
             *    0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, and 0xf6 used to form an Initialization vector as specified in
             *    section 2.3.4.12. If the array of bytes is not an integral multiple of blockSize bytes, pad the
             *    array with 0x00 to the next integral multiple of blockSize bytes.
             * 4. Assign the encryptedHmacKey attribute to the base64-encoded form of the result of step 3.
             */
            byte[] vec    = CryptoFunctions.GenerateIv(hashAlgo, header.KeySalt, kIntegrityKeyBlock, blockSize);
            Cipher cipher = CryptoFunctions.GetCipher(secretKey, cipherAlgo, ver.ChainingMode, vec, Cipher.DECRYPT_MODE);

            byte[] hmacKey = cipher.DoFinal(header.GetEncryptedHmacKey());
            hmacKey = CryptoFunctions.GetBlock0(hmacKey, hashAlgo.hashSize);

            /**
             * 5. Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
             *    which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
             *    Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
             *    used as the message.
             * 6. Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
             *    0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
             * 7. Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6.
             */
            vec    = CryptoFunctions.GenerateIv(hashAlgo, header.KeySalt, kIntegrityValueBlock, blockSize);
            cipher = CryptoFunctions.GetCipher(secretKey, cipherAlgo, ver.ChainingMode, vec, Cipher.DECRYPT_MODE);
            byte[] hmacValue = cipher.DoFinal(header.GetEncryptedHmacValue());
            hmacValue = CryptoFunctions.GetBlock0(hmacValue, hashAlgo.hashSize);

            if (Arrays.Equals(verifierHashDec, verifierHash))
            {
                SetSecretKey(secretKey);
                SetIntegrityHmacKey(hmacKey);
                SetIntegrityHmacValue(hmacValue);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #7
0
        public override void ConfirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt)
        {
            AgileEncryptionVerifier ver = builder.GetVerifier();

            ver.Salt = (/*setter*/ verifierSalt);
            AgileEncryptionHeader header = builder.GetHeader();

            header.KeySalt = (/*setter*/ keySalt);
            HashAlgorithm hashAlgo = ver.HashAlgorithm;

            int blockSize = header.BlockSize;

            pwHash = CryptoFunctions.HashPassword(password, hashAlgo, verifierSalt, ver.SpinCount);

            /**
             * encryptedVerifierHashInput: This attribute MUST be generated by using the following steps:
             * 1. Generate a random array of bytes with the number of bytes used specified by the saltSize
             *    attribute.
             * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
             *    the binary byte array used to create the saltValue attribute, and a blockKey byte array
             *    consisting of the following bytes: 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, and 0x79.
             * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
             *    attribute as an Initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
             *    integral multiple of blockSize bytes, pad the array with 0x00 to the next integral multiple of
             *    blockSize bytes.
             * 4. Use base64 to encode the result of step 3.
             */
            byte[] encryptedVerifier = AgileDecryptor.hashInput(builder, pwHash, AgileDecryptor.kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE);
            ver.EncryptedVerifier = (/*setter*/ encryptedVerifier);


            /**
             * encryptedVerifierHashValue: This attribute MUST be generated by using the following steps:
             * 1. Obtain the hash value of the random array of bytes generated in step 1 of the steps for
             *    encryptedVerifierHashInput.
             * 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
             *    the binary byte array used to create the saltValue attribute, and a blockKey byte array
             *    consisting of the following bytes: 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, and 0x4e.
             * 3. Encrypt the hash value obtained in step 1 by using the binary form of the saltValue attribute as
             *    an Initialization vector as specified in section 2.3.4.12. If hashSize is not an integral multiple of
             *    blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes.
             * 4. Use base64 to encode the result of step 3.
             */
            MessageDigest hashMD = CryptoFunctions.GetMessageDigest(hashAlgo);

            byte[] hashedVerifier        = hashMD.Digest(verifier);
            byte[] encryptedVerifierHash = AgileDecryptor.hashInput(builder, pwHash, AgileDecryptor.kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE);
            ver.EncryptedVerifierHash = (/*setter*/ encryptedVerifierHash);

            /**
             * encryptedKeyValue: This attribute MUST be generated by using the following steps:
             * 1. Generate a random array of bytes that is the same size as specified by the
             *    Encryptor.KeyData.keyBits attribute of the parent element.
             * 2. Generate an encryption key as specified in section 2.3.4.11, using the user-supplied password,
             *    the binary byte array used to create the saltValue attribute, and a blockKey byte array
             *    consisting of the following bytes: 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, and 0xd6.
             * 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
             *    attribute as an Initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
             *    integral multiple of blockSize bytes, pad the array with 0x00 to an integral multiple of
             *    blockSize bytes.
             * 4. Use base64 to encode the result of step 3.
             */
            byte[] encryptedKey = AgileDecryptor.hashInput(builder, pwHash, AgileDecryptor.kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE);
            ver.EncryptedKey = (/*setter*/ encryptedKey);

            ISecretKey secretKey = new SecretKeySpec(keySpec, ver.CipherAlgorithm.jceId);

            SetSecretKey(secretKey);

            /*
             * 2.3.4.14 DataIntegrity Generation (Agile Encryption)
             *
             * The DataIntegrity element Contained within an Encryption element MUST be generated by using
             * the following steps:
             * 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor
             *    Contained within the KeyEncryptors sequence. Use this key for encryption operations in the
             *    remaining steps of this section.
             * 2. Generate a random array of bytes, known as Salt, of the same length as the value of the
             *    KeyData.HashSize attribute.
             * 3. Encrypt the random array of bytes generated in step 2 by using the binary form of the
             *    KeyData.saltValue attribute and a blockKey byte array consisting of the following bytes:
             *    0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, and 0xf6 used to form an Initialization vector as
             *    specified in section 2.3.4.12. If the array of bytes is not an integral multiple of blockSize
             *    bytes, pad the array with 0x00 to the next integral multiple of blockSize bytes.
             * 4. Assign the encryptedHmacKey attribute to the base64-encoded form of the result of step 3.
             * 5. Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
             *    which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
             *    Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
             *    used as the message.
             * 6. Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
             *    0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
             * 7.  Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6.
             */
            this.integritySalt = integritySalt;

            try {
                byte[] vec              = CryptoFunctions.GenerateIv(hashAlgo, header.KeySalt, AgileDecryptor.kIntegrityKeyBlock, header.BlockSize);
                Cipher cipher           = CryptoFunctions.GetCipher(secretKey, ver.CipherAlgorithm, ver.ChainingMode, vec, Cipher.ENCRYPT_MODE);
                byte[] FilledSalt       = CryptoFunctions.GetBlock0(integritySalt, AgileDecryptor.GetNextBlockSize(integritySalt.Length, blockSize));
                byte[] encryptedHmacKey = cipher.DoFinal(FilledSalt);
                header.SetEncryptedHmacKey(encryptedHmacKey);

                cipher = Cipher.GetInstance("RSA");
                foreach (AgileEncryptionVerifier.AgileCertificateEntry ace in ver.GetCertificates())
                {
                    cipher.Init(Cipher.ENCRYPT_MODE, ace.x509.GetPublicKey());
                    ace.encryptedKey = cipher.DoFinal(GetSecretKey().GetEncoded());
                    CryptoFunctions.Mac x509Hmac = CryptoFunctions.GetMac(hashAlgo);
                    x509Hmac.Init(GetSecretKey());
                    ace.certVerifier = x509Hmac.DoFinal(ace.x509.GetEncoded());
                }
            } catch (Exception e) {
                throw new EncryptedDocumentException(e);
            }
        }