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; } }
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)); } }
/** * 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)); } }
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); }
/** * 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(); }
/** * 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); } }
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); } }