You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AgileEncryptionVerifier.java 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.poifs.crypt.agile;
  16. import org.apache.poi.EncryptedDocumentException;
  17. import org.apache.poi.poifs.crypt.ChainingMode;
  18. import org.apache.poi.poifs.crypt.CipherAlgorithm;
  19. import org.apache.poi.poifs.crypt.EncryptionVerifier;
  20. import org.apache.poi.poifs.crypt.HashAlgorithm;
  21. /**
  22. * Used when checking if a key is valid for a document
  23. */
  24. public class AgileEncryptionVerifier extends EncryptionVerifier {
  25. private int keyBits = -1;
  26. private int blockSize = -1;
  27. @SuppressWarnings("unused")
  28. public AgileEncryptionVerifier(String descriptor) {
  29. this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor));
  30. }
  31. protected AgileEncryptionVerifier(EncryptionDocument ed) {
  32. PasswordKeyEncryptor keyData = null;
  33. for (KeyEncryptor ke : ed.getKeyEncryptors()) {
  34. keyData = ke.getPasswordKeyEncryptor();
  35. if (keyData != null) {
  36. break;
  37. }
  38. }
  39. if (keyData == null || keyData.getHashSize() == null) {
  40. throw new IllegalArgumentException("encryptedKey not set");
  41. }
  42. setCipherAlgorithm(keyData.getCipherAlgorithm());
  43. setKeySize(keyData.getKeyBits());
  44. int blockSize = keyData.getBlockSize();
  45. setBlockSize(blockSize);
  46. int hashSize = keyData.getHashSize();
  47. HashAlgorithm ha = keyData.getHashAlgorithm();
  48. setHashAlgorithm(ha);
  49. if (getHashAlgorithm().hashSize != hashSize) {
  50. throw new EncryptedDocumentException("Unsupported hash algorithm: " +
  51. keyData.getHashAlgorithm() + " @ " + hashSize + " bytes");
  52. }
  53. Integer spinCount = keyData.getSpinCount();
  54. if (spinCount != null) {
  55. setSpinCount(spinCount);
  56. }
  57. setEncryptedVerifier(keyData.getEncryptedVerifierHashInput());
  58. setSalt(keyData.getSaltValue());
  59. setEncryptedKey(keyData.getEncryptedKeyValue());
  60. setEncryptedVerifierHash(keyData.getEncryptedVerifierHashValue());
  61. Integer saltSize = keyData.getSaltSize();
  62. if (saltSize == null || saltSize != getSalt().length) {
  63. throw new EncryptedDocumentException("Invalid salt size");
  64. }
  65. setChainingMode(keyData.getCipherChaining());
  66. if (keyData.getCipherChaining() != ChainingMode.cbc && keyData.getCipherChaining() != ChainingMode.cfb) {
  67. throw new EncryptedDocumentException("Unsupported chaining mode - "+ keyData.getCipherChaining());
  68. }
  69. }
  70. public AgileEncryptionVerifier(CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
  71. setCipherAlgorithm(cipherAlgorithm);
  72. setHashAlgorithm(hashAlgorithm);
  73. setChainingMode(chainingMode);
  74. setKeySize(keyBits);
  75. setBlockSize(blockSize);
  76. setSpinCount(100000); // TODO: use parameter
  77. }
  78. public AgileEncryptionVerifier(AgileEncryptionVerifier other) {
  79. super(other);
  80. keyBits = other.keyBits;
  81. blockSize = other.blockSize;
  82. }
  83. @Override
  84. public void setSalt(byte[] salt) {
  85. if (salt == null || salt.length != getCipherAlgorithm().blockSize) {
  86. throw new EncryptedDocumentException("invalid verifier salt");
  87. }
  88. super.setSalt(salt);
  89. }
  90. // make method visible for this package
  91. @Override
  92. public void setEncryptedVerifier(byte[] encryptedVerifier) {
  93. super.setEncryptedVerifier(encryptedVerifier);
  94. }
  95. // make method visible for this package
  96. @Override
  97. public void setEncryptedVerifierHash(byte[] encryptedVerifierHash) {
  98. super.setEncryptedVerifierHash(encryptedVerifierHash);
  99. }
  100. // make method visible for this package
  101. @Override
  102. public void setEncryptedKey(byte[] encryptedKey) {
  103. super.setEncryptedKey(encryptedKey);
  104. }
  105. @Override
  106. public AgileEncryptionVerifier copy() {
  107. return new AgileEncryptionVerifier(this);
  108. }
  109. /**
  110. * The keysize (in bits) of the verifier data. This usually equals the keysize of the header,
  111. * but only on a few exceptions, like files generated by Office for Mac, can be
  112. * different.
  113. *
  114. * @return the keysize (in bits) of the verifier.
  115. */
  116. public int getKeySize() {
  117. return keyBits;
  118. }
  119. /**
  120. * The blockSize (in bytes) of the verifier data.
  121. * This usually equals the blocksize of the header.
  122. *
  123. * @return the blockSize (in bytes) of the verifier,
  124. */
  125. public int getBlockSize() {
  126. return blockSize;
  127. }
  128. /**
  129. * Sets the keysize (in bits) of the verifier
  130. *
  131. * @param keyBits the keysize (in bits)
  132. */
  133. public void setKeySize(int keyBits) {
  134. this.keyBits = keyBits;
  135. for (int allowedBits : getCipherAlgorithm().allowedKeySize) {
  136. if (allowedBits == keyBits) {
  137. return;
  138. }
  139. }
  140. throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for cipher "+getCipherAlgorithm());
  141. }
  142. /**
  143. * Sets the blockSize (in bytes) of the verifier
  144. *
  145. * @param blockSize the blockSize (in bytes)
  146. */
  147. public void setBlockSize(int blockSize) {
  148. this.blockSize = blockSize;
  149. }
  150. @Override
  151. public final void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm) {
  152. super.setCipherAlgorithm(cipherAlgorithm);
  153. if (cipherAlgorithm.allowedKeySize.length == 1) {
  154. setKeySize(cipherAlgorithm.defaultKeySize);
  155. }
  156. }
  157. }