Returns a Feed for the specified feed id, and will attempt to decrypt any encrypted content with the specified key. @param urn a feed or entry urn id. @param decryptionKey one or more private keys used to attempt to decrypt content. @return a Feed containing the latest entries
(String urn, PrivateKey[] decryptionKeys)
| 91 | * @return a Feed containing the latest entries for this feed id. |
| 92 | */ |
| 93 | public Feed pull(String urn, PrivateKey[] decryptionKeys) { |
| 94 | Feed feed = pull(urn); |
| 95 | if ( feed == null ) { |
| 96 | return null; |
| 97 | } |
| 98 | |
| 99 | Content content; |
| 100 | MimeType contentType; |
| 101 | for (Entry entry : feed.getEntries()) { |
| 102 | content = entry.getContentElement(); |
| 103 | if (content != null |
| 104 | && (contentType = content.getMimeType()) != null |
| 105 | && "application/xenc+xml".equals(contentType.toString())) { |
| 106 | |
| 107 | // if this message was intended for us, we will be able to |
| 108 | // decrypt one of the elements into an AES key to decrypt the |
| 109 | // encrypted entry itself |
| 110 | |
| 111 | QName publicEncryptName = new QName(Common.NS_URI, |
| 112 | Common.ENCRYPT); |
| 113 | QName publicSignName = new QName(Common.NS_URI, Common.SIGN); |
| 114 | QName encryptedDataName = new QName( |
| 115 | "http://www.w3.org/2001/04/xmlenc#", "EncryptedData"); |
| 116 | QName cipherDataName = new QName( |
| 117 | "http://www.w3.org/2001/04/xmlenc#", "CipherData"); |
| 118 | QName cipherValueName = new QName( |
| 119 | "http://www.w3.org/2001/04/xmlenc#", "CipherValue"); |
| 120 | |
| 121 | String encodedBytes; |
| 122 | byte[] decodedBytes; |
| 123 | Element publicKeyElement, cipherData, cipherValue, result; |
| 124 | List<Element> encryptedElements = content.getElements(); |
| 125 | int lastIndex = encryptedElements.size() - 1; |
| 126 | Element element; |
| 127 | PublicKey publicKey = null; |
| 128 | byte[] decryptedKey = null; |
| 129 | |
| 130 | publicKeyElement = feed.getFirstChild(publicEncryptName); |
| 131 | if (publicKeyElement == null) { |
| 132 | // fall back on signing key |
| 133 | publicKeyElement = feed.getFirstChild(publicSignName); |
| 134 | } |
| 135 | if (publicKeyElement != null |
| 136 | && publicKeyElement.getText() != null) { |
| 137 | try { |
| 138 | publicKey = Common.toPublicKeyFromX509(publicKeyElement |
| 139 | .getText()); |
| 140 | } catch (GeneralSecurityException gse) { |
| 141 | log.error("Could not parse public key: " |
| 142 | + publicKeyElement); |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | if (publicKey != null) { |
| 147 | |
| 148 | // TODO: if we're the author, we can start loop at |
| 149 | // (lastIndex-1) |
| 150 | for (int i = 0; i < encryptedElements.size(); i++) { |