From dfaac4e407de0697053498cffe0ea3d4e7f227cb Mon Sep 17 00:00:00 2001 From: "Christian P. MOMON" Date: Tue, 6 Apr 2021 19:22:18 +0200 Subject: [PATCH] Added PrivateBin feature. --- lib/json-simple-1.1.1-source.zip | Bin 0 -> 24688 bytes lib/json-simple-1.1.1.jar | Bin 0 -> 23737 bytes .../hebdobot/cli/HebdobotConfigFile.java | 17 +- src/org/april/hebdobot/privatebin/Base58.java | 208 ++++++++++++ .../hebdobot/privatebin/BurnAfterReading.java | 57 ++++ .../hebdobot/privatebin/Compression.java | 57 ++++ .../april/hebdobot/privatebin/Expiration.java | 64 ++++ .../april/hebdobot/privatebin/Formatter.java | 58 ++++ .../hebdobot/privatebin/OpenDiscussion.java | 57 ++++ .../hebdobot/privatebin/PrivatebinClient.java | 301 ++++++++++++++++++ .../privatebin/PrivatebinException.java | 70 ++++ .../privatebin/PrivatebinSettings.java | 105 ++++++ .../privatebin/PrivatebinClientTest.java | 47 +++ 13 files changed, 1040 insertions(+), 1 deletion(-) create mode 100644 lib/json-simple-1.1.1-source.zip create mode 100644 lib/json-simple-1.1.1.jar create mode 100644 src/org/april/hebdobot/privatebin/Base58.java create mode 100644 src/org/april/hebdobot/privatebin/BurnAfterReading.java create mode 100644 src/org/april/hebdobot/privatebin/Compression.java create mode 100644 src/org/april/hebdobot/privatebin/Expiration.java create mode 100644 src/org/april/hebdobot/privatebin/Formatter.java create mode 100644 src/org/april/hebdobot/privatebin/OpenDiscussion.java create mode 100644 src/org/april/hebdobot/privatebin/PrivatebinClient.java create mode 100644 src/org/april/hebdobot/privatebin/PrivatebinException.java create mode 100644 src/org/april/hebdobot/privatebin/PrivatebinSettings.java create mode 100644 test/org/april/hebdobot/privatebin/PrivatebinClientTest.java diff --git a/lib/json-simple-1.1.1-source.zip b/lib/json-simple-1.1.1-source.zip new file mode 100644 index 0000000000000000000000000000000000000000..4f2ee8620ecd59081012ed698cc560994ad21c97 GIT binary patch literal 24688 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 A{Qv*} literal 0 HcmV?d00001 diff --git a/src/org/april/hebdobot/cli/HebdobotConfigFile.java b/src/org/april/hebdobot/cli/HebdobotConfigFile.java index e673b47..9b10815 100644 --- a/src/org/april/hebdobot/cli/HebdobotConfigFile.java +++ b/src/org/april/hebdobot/cli/HebdobotConfigFile.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2017-2018 Christian Pierre MOMON + * Copyright (C) 2017-2021 Christian Pierre MOMON * * This file is part of (April) Hebdobot. * @@ -346,6 +346,21 @@ public class HebdobotConfigFile extends Properties return result; } + /** + * Gets the name. + * + * @return the name + */ + public String getPrivateBinUrl() + { + String result; + + result = getProperty("privatebin.url"); + + // + return result; + } + /** * Gets the review directory. * diff --git a/src/org/april/hebdobot/privatebin/Base58.java b/src/org/april/hebdobot/privatebin/Base58.java new file mode 100644 index 0000000..6502903 --- /dev/null +++ b/src/org/april/hebdobot/privatebin/Base58.java @@ -0,0 +1,208 @@ +/* + * Copyright 2021 Christian Pierre MOMON + * Copyright 2020 Dr Ian Preston ianopolous + * Copyright 2018 Andreas Schildbach + * Copyright 2011 Google Inc. + * + * From: + * https://github.com/multiformats/java-multibase/blob/master/src/main/java/io/ipfs/multibase/Base58.java + * https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/org/bitcoinj/core/Base58.java + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.april.hebdobot.privatebin; + +import java.math.BigInteger; +import java.util.Arrays; + +/** + * Base58 is a way to encode Bitcoin addresses (or arbitrary data) as + * alphanumeric strings. + *

+ * Note that this is not the same base58 as used by Flickr, which you may find + * referenced around the Internet. + *

+ * Satoshi explains: why base-58 instead of standard base-64 encoding? + *

    + *
  • Don't want 0OIl characters that look the same in some fonts and could be + * used to create visually identical looking account numbers.
  • + *
  • A string with non-alphanumeric characters is not as easily accepted as an + * account number.
  • + *
  • E-mail usually won't line-break if there's no punctuation to break + * at.
  • + *
  • Doubleclicking selects the whole number as one word if it's all + * alphanumeric.
  • + *
+ *

+ * However, note that the encoding/decoding runs in O(n²) time, so it is + * not useful for large data. + *

+ * The basic idea of the encoding is to treat the data bytes as a large number + * represented using base-256 digits, convert the number to be represented using + * base-58 digits, preserve the exact number of leading zeros (which are + * otherwise lost during the mathematical operations on the numbers), and + * finally represent the resulting base-58 digits as alphanumeric ASCII + * characters. + */ +public class Base58 +{ + public static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); + private static final char ENCODED_ZERO = ALPHABET[0]; + private static final int[] INDEXES = new int[128]; + static + { + Arrays.fill(INDEXES, -1); + for (int i = 0; i < ALPHABET.length; i++) + { + INDEXES[ALPHABET[i]] = i; + } + } + + /** + * Decodes the given base58 string into the original data bytes. + * + * @param input + * the base58-encoded string to decode + * @return the decoded data bytes + */ + public static byte[] decode(final String input) + { + if (input.length() == 0) + { + return new byte[0]; + } + // Convert the base58-encoded ASCII chars to a base58 byte sequence + // (base58 digits). + byte[] input58 = new byte[input.length()]; + for (int i = 0; i < input.length(); ++i) + { + char c = input.charAt(i); + int digit = c < 128 ? INDEXES[c] : -1; + if (digit < 0) + { + throw new IllegalStateException("InvalidCharacter in base 58"); + } + input58[i] = (byte) digit; + } + // Count leading zeros. + int zeros = 0; + while (zeros < input58.length && input58[zeros] == 0) + { + ++zeros; + } + // Convert base-58 digits to base-256 digits. + byte[] decoded = new byte[input.length()]; + int outputStart = decoded.length; + for (int inputStart = zeros; inputStart < input58.length;) + { + decoded[--outputStart] = divmod(input58, inputStart, 58, 256); + if (input58[inputStart] == 0) + { + ++inputStart; // optimization - skip leading zeros + } + } + // Ignore extra leading zeroes that were added during the calculation. + while (outputStart < decoded.length && decoded[outputStart] == 0) + { + ++outputStart; + } + // Return decoded data (including original number of leading zeros). + return Arrays.copyOfRange(decoded, outputStart - zeros, decoded.length); + } + + public static BigInteger decodeToBigInteger(final String input) + { + return new BigInteger(1, decode(input)); + } + + /** + * Divides a number, represented as an array of bytes each containing a + * single digit in the specified base, by the given divisor. The given + * number is modified in-place to contain the quotient, and the return value + * is the remainder. + * + * @param number + * the number to divide + * @param firstDigit + * the index within the array of the first non-zero digit (this + * is used for optimization by skipping the leading zeros) + * @param base + * the base in which the number's digits are represented (up to + * 256) + * @param divisor + * the number to divide by (up to 256) + * @return the remainder of the division operation + */ + private static byte divmod(final byte[] number, final int firstDigit, final int base, final int divisor) + { + // this is just long division which accounts for the base of the input + // digits + int remainder = 0; + for (int i = firstDigit; i < number.length; i++) + { + int digit = number[i] & 0xFF; + int temp = remainder * base + digit; + number[i] = (byte) (temp / divisor); + remainder = temp % divisor; + } + return (byte) remainder; + } + + /** + * Encodes the given bytes as a base58 string (no checksum is appended). + * + * @param input + * the bytes to encode + * @return the base58-encoded string + */ + public static String encode(byte[] input) + { + if (input.length == 0) + { + return ""; + } + // Count leading zeros. + int zeros = 0; + while (zeros < input.length && input[zeros] == 0) + { + ++zeros; + } + // Convert base-256 digits to base-58 digits (plus conversion to ASCII + // characters) + input = Arrays.copyOf(input, input.length); // since we modify it + // in-place + char[] encoded = new char[input.length * 2]; // upper bound + int outputStart = encoded.length; + for (int inputStart = zeros; inputStart < input.length;) + { + encoded[--outputStart] = ALPHABET[divmod(input, inputStart, 256, 58)]; + if (input[inputStart] == 0) + { + ++inputStart; // optimization - skip leading zeros + } + } + // Preserve exactly as many leading encoded zeros in output as there + // were leading zeros in input. + while (outputStart < encoded.length && encoded[outputStart] == ENCODED_ZERO) + { + ++outputStart; + } + while (--zeros >= 0) + { + encoded[--outputStart] = ENCODED_ZERO; + } + // Return encoded string (including encoded leading zeros). + return new String(encoded, outputStart, encoded.length - outputStart); + } +} \ No newline at end of file diff --git a/src/org/april/hebdobot/privatebin/BurnAfterReading.java b/src/org/april/hebdobot/privatebin/BurnAfterReading.java new file mode 100644 index 0000000..e5cf03f --- /dev/null +++ b/src/org/april/hebdobot/privatebin/BurnAfterReading.java @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2019-2021 Christian Pierre MOMON + * + * This file is part of (April) Hebdobot. + * + * Hebdobot is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hebdobot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Hebdobot. If not, see + */ +package org.april.hebdobot.privatebin; + +/** + * The Enum Option. + */ +public enum BurnAfterReading +{ + ON("1"), + OFF("0"); + + private final String value; + + /** + * Instantiates a new option. + * + * @param value + * the value + */ + private BurnAfterReading(final String value) + { + this.value = value; + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() + { + String result; + + result = this.value; + + // + return result; + } +} diff --git a/src/org/april/hebdobot/privatebin/Compression.java b/src/org/april/hebdobot/privatebin/Compression.java new file mode 100644 index 0000000..874f3dd --- /dev/null +++ b/src/org/april/hebdobot/privatebin/Compression.java @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2021 Christian Pierre MOMON + * + * This file is part of (April) Hebdobot. + * + * Hebdobot is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hebdobot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Hebdobot. If not, see + */ +package org.april.hebdobot.privatebin; + +/** + * The Enum Compression. + */ +public enum Compression +{ + NONE("none"), + ZLIB("zlib"); + + private final String value; + + /** + * Instantiates a new option. + * + * @param value + * the value + */ + private Compression(final String value) + { + this.value = value; + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() + { + String result; + + result = this.value; + + // + return result; + } +} diff --git a/src/org/april/hebdobot/privatebin/Expiration.java b/src/org/april/hebdobot/privatebin/Expiration.java new file mode 100644 index 0000000..99eb799 --- /dev/null +++ b/src/org/april/hebdobot/privatebin/Expiration.java @@ -0,0 +1,64 @@ +/** + * Copyright (C) 2017-2021 Christian Pierre MOMON + * Copyright (C) 2011-2013 Nicolas Vinot + * + * This file is part of (April) Hebdobot. + * + * Hebdobot is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hebdobot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Hebdobot. If not, see + */ +package org.april.hebdobot.privatebin; + +/** + * The Enum Expiration. + */ +public enum Expiration +{ + MINUTE_5("5min"), + MINUTE_10("10min"), + HOUR_1("1hour"), + DAY_1("1day"), + WEEK_1("1week"), + MONTH_1("1month"), + YEAR_1("1year"), + NEVER("never"); + + private final String value; + + /** + * Instantiates a new expiration. + * + * @param value + * the value + */ + private Expiration(final String value) + { + this.value = value; + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() + { + String result; + + result = this.value; + + // + return result; + } +} diff --git a/src/org/april/hebdobot/privatebin/Formatter.java b/src/org/april/hebdobot/privatebin/Formatter.java new file mode 100644 index 0000000..32f35b5 --- /dev/null +++ b/src/org/april/hebdobot/privatebin/Formatter.java @@ -0,0 +1,58 @@ +/** + * Copyright (C) 2019-2021 Christian Pierre MOMON + * + * This file is part of (April) Hebdobot. + * + * Hebdobot is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hebdobot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Hebdobot. If not, see + */ +package org.april.hebdobot.privatebin; + +/** + * The Enum Formatter. + */ +public enum Formatter +{ + PLAINTEXT("plaintext"), + SYNTAXHIGHLIGHTING("syntaxhighlighting"), + MARKDOWN("markdown"); + + private final String value; + + /** + * Instantiates a new format. + * + * @param value + * the value + */ + private Formatter(final String value) + { + this.value = value; + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() + { + String result; + + result = this.value; + + // + return result; + } +} diff --git a/src/org/april/hebdobot/privatebin/OpenDiscussion.java b/src/org/april/hebdobot/privatebin/OpenDiscussion.java new file mode 100644 index 0000000..ac0f8aa --- /dev/null +++ b/src/org/april/hebdobot/privatebin/OpenDiscussion.java @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2019-2021 Christian Pierre MOMON + * + * This file is part of (April) Hebdobot. + * + * Hebdobot is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hebdobot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Hebdobot. If not, see + */ +package org.april.hebdobot.privatebin; + +/** + * The Enum Option. + */ +public enum OpenDiscussion +{ + ON("1"), + OFF("0"); + + private final String value; + + /** + * Instantiates a new option. + * + * @param value + * the value + */ + private OpenDiscussion(final String value) + { + this.value = value; + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() + { + String result; + + result = this.value; + + // + return result; + } +} diff --git a/src/org/april/hebdobot/privatebin/PrivatebinClient.java b/src/org/april/hebdobot/privatebin/PrivatebinClient.java new file mode 100644 index 0000000..699804e --- /dev/null +++ b/src/org/april/hebdobot/privatebin/PrivatebinClient.java @@ -0,0 +1,301 @@ +/** + * Copyright (C) 2017-2021 Christian Pierre MOMON + * Copyright (C) 2011-2013 Nicolas Vinot + * + * This file is part of (April) Hebdobot. + * + * Hebdobot is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hebdobot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Hebdobot. If not, see + */ +package org.april.hebdobot.privatebin; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.Random; +import java.util.zip.Deflater; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.KeyGenerator; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; +import javax.net.ssl.HttpsURLConnection; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.message.BasicNameValuePair; +import org.april.hebdobot.HebdobotException; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import fr.devinsy.strings.StringList; + +/** + * The Class PastebinClient. + */ +public class PrivatebinClient +{ + private String serverUrl; + private Compression compression; + + /** + * Instantiates a new privatebin client. + * + * @param serverUrl + * the server url + */ + public PrivatebinClient(final String serverUrl) + { + this.serverUrl = serverUrl; + this.compression = Compression.ZLIB; + } + + /** + * Paste. + * + * @param serverUrl + * the server url + * @param expirationDate + * the expiration + * @param burnAfterReading + * the burn after reading + * @param openDiscussion + * the open discussion + * @return the string + * @throws HebdobotException + * the hebdobot exception + * @throws PrivatebinException + */ + public String paste(final String text, final Expiration expiration, final Formatter formatter, final BurnAfterReading burnAfterReading, + final OpenDiscussion openDiscussion) throws PrivatebinException + { + String result; + + result = null; + try + { + if (expiration == null) + { + throw new IllegalArgumentException("Null parameter expiration."); + } + else if (formatter == null) + { + throw new IllegalArgumentException("Null parameter formatter."); + } + else if (burnAfterReading == null) + { + throw new IllegalArgumentException("Null parameter burn after reading."); + } + else if (openDiscussion == null) + { + throw new IllegalArgumentException("Null parameter open discussion."); + } + else + { + // Note: the following code is based on: + // https://github.com/PrivateBin/PrivateBin/wiki/API + // https://github.com/kkingsley-BF/PrivateBin-Groovy/blob/master/Paste.groovy + + // Optional parameters + // =================== + + // Location of local file to attach, leave quotes empty for no + // file + String localAttachmentFilename = ""; + // Paste attachment name, leave quotes empty for no file + String pasteAttachmentFilename = ""; + // Read file contents into paste, leave quotes empty no no file + String plaintextFileLocation = ""; + // Set paste password, leave quotes empty for no password + String userPastePassword = ""; + + // + + // Generate password. + KeyGenerator keyGen = KeyGenerator.getInstance("AES"); + keyGen.init(192); + String randomPassword = Base64.getEncoder().encodeToString(keyGen.generateKey().getEncoded()); + String customPassword = randomPassword + userPastePassword; + + // Generate IV. + byte[] cipherIVBytes = new byte[16]; + new Random().nextBytes(cipherIVBytes); + String cipherIVEncoded = Base64.getEncoder().encodeToString(cipherIVBytes); + + // Generate salt. + byte[] kdfSaltBytes = new byte[8]; + new Random().nextBytes(kdfSaltBytes); + String kdfSaltEncoded = Base64.getEncoder().encodeToString(kdfSaltBytes); + + // Build message to encrypt. + String pasteData = "{\"paste\":\"" + text + "\"}"; + + // Compression. + byte[] pasteDataBytes; + if (StringUtils.equals(this.compression.toString(), "zlib")) + { + Deflater zipDeflater = new Deflater(); + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + zipDeflater.setInput(pasteData.getBytes()); + zipDeflater.finish(); + byte[] buffer = new byte[1024]; + while (!zipDeflater.finished()) + { + int count = zipDeflater.deflate(buffer); + stream.write(buffer, 0, count); + } + byte[] output; + output = stream.toByteArray(); + stream.close(); + zipDeflater.end(); + // Need to remove the header + pasteDataBytes = Arrays.copyOfRange(output, 2, output.length - 4); + } + else + { + pasteDataBytes = pasteData.getBytes(); + } + + // Generate secret key for cipher. + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); + KeySpec passwordBasedEncryptionKeySpec = new PBEKeySpec(customPassword.toCharArray(), kdfSaltBytes, 100000, 256); + SecretKey secret = new SecretKeySpec(factory.generateSecret(passwordBasedEncryptionKeySpec).getEncoded(), "AES"); + + // Cipher AAD. + StringList gcmTagString = new StringList(); + gcmTagString.append("["); + gcmTagString.append("["); + gcmTagString.append("\"").append(cipherIVEncoded).append("\"").append(","); + gcmTagString.append("\"").append(kdfSaltEncoded).append("\"").append(","); + gcmTagString.append("100000,256,128,"); + gcmTagString.append("\"").append("aes").append("\"").append(","); + gcmTagString.append("\"").append("gcm").append("\"").append(","); + gcmTagString.append("\"").append(this.compression).append("\""); + gcmTagString.append("]"); + gcmTagString.append(","); + gcmTagString.append("\"").append(formatter).append("\"").append(","); + gcmTagString.append(openDiscussion).append(","); + gcmTagString.append(burnAfterReading); + gcmTagString.append("]"); + byte[] gcmBytes = gcmTagString.toString().getBytes(); + + System.out.println("gcm=" + gcmTagString.toString()); + + // Generate cipher text. + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + GCMParameterSpec spec = new GCMParameterSpec(128, cipherIVBytes); + cipher.init(Cipher.ENCRYPT_MODE, secret, spec); + cipher.updateAAD(gcmBytes); + byte[] cipherTextBytes = cipher.doFinal(pasteDataBytes); + String cipherText = Base64.getEncoder().encodeToString(cipherTextBytes); + + // Create POST payload. + StringList payload = new StringList(); + payload.append("{"); + payload.append("\"v\":2,"); + payload.append("\"adata\":").append(gcmTagString.toString()).append(","); + payload.append("\"ct\":\"").append(cipherText).append("\","); + payload.append("\"meta\":{\"expire\":\"").append(expiration).append("\"}"); + payload.append("}"); + + // POST Request. + HttpsURLConnection pasteRequest = (HttpsURLConnection) new URL(this.serverUrl).openConnection(); + pasteRequest.setRequestMethod("POST"); + pasteRequest.setDoOutput(true); + pasteRequest.setRequestProperty("X-Requested-With", "JSONHttpRequest"); + pasteRequest.getOutputStream().write(payload.toString().getBytes()); + System.out.println("PAYLOAD=" + payload.toString()); + + // Server response. + int responseCode = pasteRequest.getResponseCode(); + System.out.println("Server response: " + responseCode); + if (responseCode == 200) + { + + String out = IOUtils.toString(pasteRequest.getInputStream(), "UTF-8"); + System.out.println("===> " + out); + + JSONObject parser = (JSONObject) new JSONParser().parse(out); + String status = parser.get("status").toString(); + if (StringUtils.equals(status, "0")) + { + String id = parser.get("id").toString(); + String pasteURL = parser.get("url").toString(); + String deleteToken = parser.get("deletetoken").toString(); + String finalURL = this.serverUrl + pasteURL + "#" + Base58.encode(randomPassword.getBytes()); + String deleteURL = this.serverUrl + pasteURL + "&deletetoken=" + deleteToken; + System.out.println("SUCESS"); + System.out.println("Paste URL: " + finalURL); + System.out.println("Delete URL: " + deleteURL); + } + else + { + String output = parser.get("message").toString(); + System.out.println("message=" + output); + throw new PrivatebinException(out); + } + } + } + } + catch (BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException | InvalidKeyException | InvalidKeySpecException + | NoSuchAlgorithmException | NoSuchPaddingException | ParseException | UnsupportedEncodingException + | ClientProtocolException exception) + { + throw new PrivatebinException(exception); + } + catch (IOException exception) + { + exception.printStackTrace(); + throw new PrivatebinException(exception); + } + + // + return result; + } + + /** + * Sets the parameter. + * + * @param params + * the params + * @param name + * the name + * @param value + * the value + */ + private static void setParameter(final List params, final String name, final String value) + { + if (value != null) + { + params.add(new BasicNameValuePair(name, value)); + } + } +} diff --git a/src/org/april/hebdobot/privatebin/PrivatebinException.java b/src/org/april/hebdobot/privatebin/PrivatebinException.java new file mode 100644 index 0000000..1891e12 --- /dev/null +++ b/src/org/april/hebdobot/privatebin/PrivatebinException.java @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2021 Christian Pierre MOMON + * + * This file is part of (April) Hebdobot. + * + * Hebdobot is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hebdobot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Hebdobot. If not, see + */ +package org.april.hebdobot.privatebin; + +/** + * The Class PrivateBinException. + */ +public class PrivatebinException extends Exception +{ + private static final long serialVersionUID = -1113543017171098521L; + + /** + * Instantiates a new private bin exception. + */ + public PrivatebinException() + { + super(); + } + + /** + * Instantiates a new private bin exception. + * + * @param message + * the message + */ + public PrivatebinException(final String message) + { + super(message); + } + + /** + * Instantiates a new private bin exception. + * + * @param message + * the message + * @param cause + * the cause + */ + public PrivatebinException(final String message, final Throwable cause) + { + super(message, cause); + } + + /** + * Instantiates a new private bin exception. + * + * @param cause + * the cause + */ + public PrivatebinException(final Throwable cause) + { + super(cause); + } +} \ No newline at end of file diff --git a/src/org/april/hebdobot/privatebin/PrivatebinSettings.java b/src/org/april/hebdobot/privatebin/PrivatebinSettings.java new file mode 100644 index 0000000..fa3c9b2 --- /dev/null +++ b/src/org/april/hebdobot/privatebin/PrivatebinSettings.java @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2019-2021 Christian Pierre MOMON + * + * This file is part of (April) Hebdobot. + * + * Hebdobot is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hebdobot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Hebdobot. If not, see + */ +package org.april.hebdobot.privatebin; + +import org.apache.commons.lang3.StringUtils; + +/** + * The Class PrivatebinSettings + */ +public class PrivatebinSettings +{ + private String serverUrl; + private String expirationDate; + private String burnAfterReading; + private String openDiscussion; + + /** + * Instantiates a new Privatebin settings. + */ + public PrivatebinSettings() + { + this.serverUrl = null; + this.expirationDate = null; + this.burnAfterReading = null; + this.openDiscussion = null; + } + + public String getBurnAfterReading() + { + return this.burnAfterReading; + } + + public String getExpirationDate() + { + return this.expirationDate; + } + + public String getOpenDiscussion() + { + return this.openDiscussion; + } + + public String getServerUrl() + { + return this.serverUrl; + } + + /** + * Checks if is valid. + * + * @return true, if is valid + */ + public boolean isValid() + { + boolean result; + + if ((StringUtils.isBlank(this.serverUrl)) || (StringUtils.containsOnly(this.serverUrl, 'X'))) + { + result = false; + } + else + { + result = true; + } + + // + return result; + } + + public void setBurnAfterReading(final String burnAfterReading) + { + this.burnAfterReading = burnAfterReading; + } + + public void setExpirationDate(final String expirationDate) + { + this.expirationDate = expirationDate; + } + + public void setOpenDiscussion(final String openDiscussion) + { + this.openDiscussion = openDiscussion; + } + + public void setServerUrl(final String serverUrl) + { + this.serverUrl = serverUrl; + } +} diff --git a/test/org/april/hebdobot/privatebin/PrivatebinClientTest.java b/test/org/april/hebdobot/privatebin/PrivatebinClientTest.java new file mode 100644 index 0000000..5521000 --- /dev/null +++ b/test/org/april/hebdobot/privatebin/PrivatebinClientTest.java @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2019-2021 Christian Pierre MOMON + * + * This file is part of (April) Hebdobot. + * + * Hebdobot is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hebdobot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Hebdobot. If not, see + */ +package org.april.hebdobot.privatebin; + +import org.junit.Test; + +/** + * The Class PrivatebinClientTest. + */ +public class PrivatebinClientTest +{ + /** + * Test paste. + * + * @throws Exception + * the exception + */ + @Test + public void testPaste00() throws Exception + { + PrivatebinClient client = new PrivatebinClient("https://cpaste.org/"); + // PrivatebinClient client = new + // PrivatebinClient("https://paste.chapril.org/"); + + String text = "This is a test."; + + String result = client.paste(text, Expiration.MINUTE_5, Formatter.PLAINTEXT, BurnAfterReading.OFF, OpenDiscussion.OFF); + + System.out.println("result:" + result); + } +}