public override bool VerifyPassword(String password) { EncryptionVerifier ver = builder.GetVerifier(); ISecretKey skey = GenerateSecretKey(password, ver); try { Cipher cipher = InitCipherForBlock(null, 0, builder, skey, Cipher.DECRYPT_MODE); byte[] encryptedVerifier = ver.EncryptedVerifier; byte[] verifier = new byte[encryptedVerifier.Length]; cipher.Update(encryptedVerifier, 0, encryptedVerifier.Length, verifier); SetVerifier(verifier); byte[] encryptedVerifierHash = ver.EncryptedVerifierHash; byte[] verifierHash = cipher.DoFinal(encryptedVerifierHash); HashAlgorithm hashAlgo = ver.HashAlgorithm; MessageDigest hashAlg = CryptoFunctions.GetMessageDigest(hashAlgo); byte[] calcVerifierHash = hashAlg.Digest(verifier); if (Arrays.Equals(calcVerifierHash, verifierHash)) { SetSecretKey(skey); return(true); } } catch (Exception e) { throw new EncryptedDocumentException(e); } return(false); }
protected internal static Cipher InitCipherForBlock(Cipher cipher, int block, IEncryptionInfoBuilder builder, ISecretKey skey, int encryptMode) { EncryptionVerifier ver = builder.GetVerifier(); HashAlgorithm hashAlgo = ver.HashAlgorithm; byte[] blockKey = new byte[4]; LittleEndian.PutUInt(blockKey, 0, block); MessageDigest hashAlg = CryptoFunctions.GetMessageDigest(hashAlgo); hashAlg.Update(skey.GetEncoded()); byte[] encKey = hashAlg.Digest(blockKey); EncryptionHeader header = builder.GetHeader(); int keyBits = header.KeySize; encKey = CryptoFunctions.GetBlock0(encKey, keyBits / 8); if (keyBits == 40) { encKey = CryptoFunctions.GetBlock0(encKey, 16); } ISecretKey key = new SecretKeySpec(encKey, skey.GetAlgorithm()); if (cipher == null) { cipher = CryptoFunctions.GetCipher(key, header.CipherAlgorithm, null, null, encryptMode); } else { cipher.Init(encryptMode, key); } return(cipher); }
public override void ConfirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt) { BinaryRC4EncryptionVerifier ver = builder.GetVerifier(); ver.SetSalt(verifierSalt); ISecretKey skey = BinaryRC4Decryptor.GenerateSecretKey(password, ver); SetSecretKey(skey); try { Cipher cipher = BinaryRC4Decryptor.InitCipherForBlock(null, 0, builder, skey, Cipher.ENCRYPT_MODE); byte[] encryptedVerifier = new byte[16]; cipher.Update(verifier, 0, 16, encryptedVerifier); ver.EncryptedVerifier = (encryptedVerifier); HashAlgorithm hashAlgo = ver.HashAlgorithm; MessageDigest hashAlg = CryptoFunctions.GetMessageDigest(hashAlgo); byte[] calcVerifierHash = hashAlg.Digest(verifier); byte[] encryptedVerifierHash = cipher.DoFinal(calcVerifierHash); ver.EncryptedVerifierHash = (encryptedVerifierHash); } catch (Exception e) { throw new EncryptedDocumentException("Password Confirmation failed", e); } }
public override bool VerifyPassword(String password) { EncryptionVerifier ver = builder.GetVerifier(); ISecretKey skey = GenerateSecretKey(password, ver, GetKeySizeInBytes()); Cipher cipher = GetCipher(skey); try { byte[] encryptedVerifier = ver.EncryptedVerifier; byte[] verifier = cipher.DoFinal(encryptedVerifier); SetVerifier(verifier); MessageDigest sha1 = CryptoFunctions.GetMessageDigest(ver.HashAlgorithm); byte[] calcVerifierHash = sha1.Digest(verifier); byte[] encryptedVerifierHash = ver.EncryptedVerifierHash; byte[] decryptedVerifierHash = cipher.DoFinal(encryptedVerifierHash); // see 2.3.4.9 Password Verification (Standard Encryption) // ... The number of bytes used by the encrypted Verifier hash MUST be 32 ... // TODO: check and Trim/pad the hashes to 32 byte[] verifierHash = Arrays.CopyOf(decryptedVerifierHash, calcVerifierHash.Length); if (Arrays.Equals(calcVerifierHash, verifierHash)) { SetSecretKey(skey); return(true); } else { return(false); } } catch (Exception e) { throw new EncryptedDocumentException(e); } }
public override void ConfirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt) { Debug.Assert(verifier != null && verifierSalt != null); CryptoAPIEncryptionVerifier ver = builder.GetVerifier(); ver.SetSalt(verifierSalt); ISecretKey skey = CryptoAPIDecryptor.GenerateSecretKey(password, ver); SetSecretKey(skey); try { Cipher cipher = InitCipherForBlock(null, 0); byte[] encryptedVerifier = new byte[verifier.Length]; cipher.Update(verifier, 0, verifier.Length, encryptedVerifier); ver.SetEncryptedVerifier(encryptedVerifier); HashAlgorithm hashAlgo = ver.HashAlgorithm; MessageDigest hashAlg = CryptoFunctions.GetMessageDigest(hashAlgo); byte[] calcVerifierHash = hashAlg.Digest(verifier); byte[] encryptedVerifierHash = cipher.DoFinal(calcVerifierHash); ver.SetEncryptedVerifierHash(encryptedVerifierHash); } catch (Exception e) { throw new EncryptedDocumentException("Password Confirmation failed", e); } }
protected internal static ISecretKey GenerateSecretKey(String password, EncryptionVerifier ver) { if (password.Length > 255) { password = password.Substring(0, 255); } HashAlgorithm hashAlgo = ver.HashAlgorithm; MessageDigest hashAlg = CryptoFunctions.GetMessageDigest(hashAlgo); byte[] hash = hashAlg.Digest(StringUtil.GetToUnicodeLE(password)); byte[] salt = ver.Salt; hashAlg.Reset(); for (int i = 0; i < 16; i++) { hashAlg.Update(hash, 0, 5); hashAlg.Update(salt); } hash = new byte[5]; Array.Copy(hashAlg.Digest(), 0, hash, 0, 5); ISecretKey skey = new SecretKeySpec(hash, ver.CipherAlgorithm.jceId); return(skey); }
/** * Fills the fields of verifier and header with the calculated hashes based * on the password and a random salt * * see [MS-OFFCRYPTO] - 2.3.4.7 ECMA-376 Document Encryption Key Generation */ public override void ConfirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt) { StandardEncryptionVerifier ver = builder.GetVerifier(); ver.SetSalt(verifierSalt); ISecretKey secretKey = StandardDecryptor.GenerateSecretKey(password, ver, GetKeySizeInBytes()); SetSecretKey(secretKey); Cipher cipher = GetCipher(secretKey, null); try { byte[] encryptedVerifier = cipher.DoFinal(verifier); MessageDigest hashAlgo = CryptoFunctions.GetMessageDigest(ver.HashAlgorithm); byte[] calcVerifierHash = hashAlgo.Digest(verifier); // 2.3.3 EncryptionVerifier ... // An array of bytes that Contains the encrypted form of the // hash of the randomly generated Verifier value. The length of the array MUST be the size of // the encryption block size multiplied by the number of blocks needed to encrypt the hash of the // Verifier. If the encryption algorithm is RC4, the length MUST be 20 bytes. If the encryption // algorithm is AES, the length MUST be 32 bytes. After decrypting the EncryptedVerifierHash // field, only the first VerifierHashSize bytes MUST be used. int encVerHashSize = ver.CipherAlgorithm.encryptedVerifierHashLength; byte[] encryptedVerifierHash = cipher.DoFinal(Arrays.CopyOf(calcVerifierHash, encVerHashSize)); ver.SetEncryptedVerifier(encryptedVerifier); ver.SetEncryptedVerifierHash(encryptedVerifierHash); } catch (Exception e) { throw new EncryptedDocumentException("Password Confirmation failed", e); } }
protected static byte[] FillAndXor(byte[] hash, byte FillByte) { byte[] buff = new byte[64]; Arrays.Fill(buff, FillByte); for (int i = 0; i < hash.Length; i++) { buff[i] = (byte)(buff[i] ^ hash[i]); } MessageDigest sha1 = CryptoFunctions.GetMessageDigest(HashAlgorithm.sha1); return(sha1.Digest(buff)); }
protected internal static ISecretKey GenerateSecretKey(String password, EncryptionVerifier ver) { if (password.Length > 255) { password = password.Substring(0, 255); } HashAlgorithm hashAlgo = ver.HashAlgorithm; MessageDigest hashAlg = CryptoFunctions.GetMessageDigest(hashAlgo); hashAlg.Update(ver.Salt); byte[] hash = hashAlg.Digest(StringUtil.GetToUnicodeLE(password)); ISecretKey skey = new SecretKeySpec(hash, ver.CipherAlgorithm.jceId); return(skey); }
/** * 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 byte[] TimeStamp(byte[] data, RevocationData revocationData) { // digest the message MessageDigest messageDigest = CryptoFunctions.GetMessageDigest(signatureConfig.GetTspDigestAlgo()); byte[] digest = messageDigest.Digest(data); throw new NotImplementedException(); //// generate the TSP request //Bigint nonce = new Bigint(128, new Random()); //TimeStampRequestGenerator requestGenerator = new TimeStampRequestGenerator(); //requestGenerator.SetCertReq(true); //String requestPolicy = signatureConfig.GetTspRequestPolicy(); //if (requestPolicy != null) //{ // requestGenerator.SetReqPolicy(new ASN1ObjectIdentifier(requestPolicy)); //} //ASN1ObjectIdentifier digestAlgoOid = mapDigestAlgoToOID(signatureConfig.GetTspDigestAlgo()); //TimeStampRequest request = requestGenerator.Generate(digestAlgoOid, digest, nonce); //byte[] encodedRequest = request.GetEncoded(); //// create the HTTP POST request //Proxy proxy = Proxy.NO_PROXY; //if (signatureConfig.ProxyUrl != null) //{ // URL proxyUrl = new URL(signatureConfig.ProxyUrl); // String host = proxyUrl.Host; // int port = proxyUrl.Port; // proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, (port == -1 ? 80 : port))); //} //HttpURLConnection huc = (HttpURLConnection)new URL(signatureConfig.TspUrl).OpenConnection(proxy); //if (signatureConfig.GetTspUser() != null) //{ // String userPassword = signatureConfig.GetTspUser() + ":" + signatureConfig.GetTspPass(); // String encoding = DatatypeConverter.PrintBase64Binary(userPassword.GetBytes(Charset.ForName("iso-8859-1"))); // huc.RequestProperty = (/*setter*/"Authorization", "Basic " + encoding); //} //huc.RequestMethod = (/*setter*/"POST"); //huc.ConnectTimeout = (/*setter*/20000); //huc.ReadTimeout = (/*setter*/20000); //huc.DoOutput = (/*setter*/true); // also Sets method to POST. //huc.RequestProperty = (/*setter*/"User-Agent", signatureConfig.UserAgent); //huc.RequestProperty = (/*setter*/"Content-Type", signatureConfig.IsTspOldProtocol() // ? "application/timestamp-request" // : "application/timestamp-query"); // "; charset=ISO-8859-1"); //OutputStream hucOut = huc.OutputStream; //hucOut.Write(encodedRequest); //// invoke TSP service //huc.Connect(); //int statusCode = huc.ResponseCode; //if (statusCode != 200) //{ // //LOG.Log(POILogger.ERROR, "Error contacting TSP server ", signatureConfig.TspUrl); // throw new IOException("Error contacting TSP server " + signatureConfig.TspUrl); //} //// HTTP input validation //String contentType = huc.GetHeaderField("Content-Type"); //if (null == contentType) //{ // throw new Exception("missing Content-Type header"); //} //MemoryStream bos = new MemoryStream(); //IOUtils.Copy(huc.InputStream, bos); ////LOG.Log(POILogger.DEBUG, "response content: ", bos.ToString()); //if (!contentType.StartsWith(signatureConfig.IsTspOldProtocol() // ? "application/timestamp-response" // : "application/timestamp-reply" //)) //{ // throw new Exception("invalid Content-Type: " + contentType); //} //if (bos.Length == 0) //{ // throw new Exception("Content-Length is zero"); //} //// TSP response parsing and validation //TimeStampResponse timeStampResponse = new TimeStampResponse(bos.ToArray()); //timeStampResponse.Validate(request); //if (0 != timeStampResponse.Status) //{ // //LOG.Log(POILogger.DEBUG, "status: " + timeStampResponse.Status); // //LOG.Log(POILogger.DEBUG, "status string: " + timeStampResponse.StatusString); // PkiFailureInfo failInfo = timeStampResponse.GetFailInfo(); // if (null != failInfo) // { // //LOG.Log(POILogger.DEBUG, "fail info int value: " + failInfo.IntValue()); // if (/*PKIFailureInfo.unacceptedPolicy*/(1 << 8) == failInfo.IntValue) // { // //LOG.Log(POILogger.DEBUG, "unaccepted policy"); // } // } // throw new Exception("timestamp response status != 0: " // + timeStampResponse.Status); //} //TimeStampToken timeStampToken = timeStampResponse.TimeStampToken; //SignerID signerId = timeStampToken.SignerID; //Bigint signerCertSerialNumber = signerId.SerialNumber; //X500Name signerCertIssuer = signerId.Issuer; ////LOG.Log(POILogger.DEBUG, "signer cert serial number: " + signerCertSerialNumber); ////LOG.Log(POILogger.DEBUG, "signer cert issuer: " + signerCertIssuer); //// TSP signer certificates retrieval //Collection<X509CertificateHolder> certificates = timeStampToken.GetCertificates().GetMatches(null); //X509CertificateHolder signerCert = null; //Dictionary<X500Name, X509CertificateHolder> certificateMap = new Dictionary<X500Name, X509CertificateHolder>(); //foreach (X509CertificateHolder certificate in certificates) //{ // if (signerCertIssuer.Equals(certificate.Issuer) // && signerCertSerialNumber.Equals(certificate.SerialNumber)) // { // signerCert = certificate; // } // certificateMap.Add(certificate.Subject, certificate); //} //// TSP signer cert path building //if (signerCert == null) //{ // throw new Exception("TSP response token has no signer certificate"); //} //List<X509Certificate> tspCertificateChain = new List<X509Certificate>(); //JcaX509CertificateConverter x509Converter = new JcaX509CertificateConverter(); //x509Converter.Provider = (/*setter*/"BC"); //X509CertificateHolder certificate = signerCert; //do //{ // //LOG.Log(POILogger.DEBUG, "Adding to certificate chain: " + certificate.Subject); // tspCertificateChain.Add(x509converter.GetCertificate(certificate)); // if (certificate.Subject.Equals(certificate.Issuer)) // { // break; // } // certificate = certificateMap.Get(certificate.Issuer); //} while (null != certificate); //// verify TSP signer signature //X509CertificateHolder holder = new X509CertificateHolder(tspCertificateChain.Get(0).Encoded); //DefaultCMSSignatureAlgorithmNameGenerator nameGen = new DefaultCMSSignatureAlgorithmNameGenerator(); //DefaultSignatureAlgorithmIdentifierFinder sigAlgoFinder = new DefaultSignatureAlgorithmIdentifierFinder(); //DefaultDigestAlgorithmIdentifierFinder hashAlgoFinder = new DefaultDigestAlgorithmIdentifierFinder(); //BcDigestCalculatorProvider calculator = new BcDigestCalculatorProvider(); //BcRSASignerInfoVerifierBuilder verifierBuilder = new BcRSASignerInfoVerifierBuilder(nameGen, sigAlgoFinder, hashAlgoFinder, calculator); //SignerInformationVerifier verifier = verifierBuilder.Build(holder); //timeStampToken.Validate(verifier); //// verify TSP signer certificate //if (signatureConfig.GetTspValidator() != null) //{ // signatureConfig.GetTspValidator().Validate(tspCertificateChain, revocationData); //} ////LOG.Log(POILogger.DEBUG, "time-stamp token time: " //// + timeStampToken.TimeStampInfo.GenTime); //byte[] timestamp = timeStampToken.GetEncoded(); //return timestamp; }
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); } }