diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java index 4716b24..e6fbcd9 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java @@ -1,7 +1,6 @@ package net.knarcraft.bookswithoutborders.command; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; -import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig; import net.knarcraft.bookswithoutborders.config.Permission; import net.knarcraft.bookswithoutborders.config.Translatable; import net.knarcraft.bookswithoutborders.utility.BookHelper; @@ -31,7 +30,7 @@ public class CommandDecrypt implements TabExecutor { StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); if (!(sender instanceof Player player)) { - BooksWithoutBorders.getStringFormatter().displayErrorMessage(sender, Translatable.ERROR_PLAYER_ONLY); + stringFormatter.displayErrorMessage(sender, Translatable.ERROR_PLAYER_ONLY); return false; } @@ -50,56 +49,65 @@ public class CommandDecrypt implements TabExecutor { return false; } - BooksWithoutBordersConfig config = BooksWithoutBorders.getConfiguration(); - //Warning: admin decrypt only allows decrypting files created by the same player. Not sure if intended - if (arguments.length == 0 && config.getAdminDecrypt() && player.hasPermission(Permission.ADMIN.toString())) { - - File encryptedDirectory = new File(config.getEncryptedBookPath()); - String[] encryptedFiles = encryptedDirectory.list(); - if (encryptedFiles == null) { - BooksWithoutBorders.sendErrorMessage(player, "Could not find any encrypted files!"); - return false; - } - - //Get the "encryption key" from the filename - String key = ""; - for (String encryptedFile : encryptedFiles) { - if (encryptedFile.contains(BookHelper.getBookFile(bookMetadata, player, true))) { - key = encryptedFile.substring(encryptedFile.indexOf("[") + 1, encryptedFile.indexOf("]")); - break; - } - } - - if (!key.equalsIgnoreCase("")) { - //Decrypt the book - ItemStack book = EncryptionHelper.loadEncryptedBook(player, key, false); - if (book != null) { - InventoryHelper.setHeldWrittenBook(player, book); - BooksWithoutBorders.sendSuccessMessage(player, "Book auto-decrypted!"); - return true; - } else { - return false; - } - } else { - BooksWithoutBorders.sendErrorMessage(player, "No matching encrypted book found!"); - return false; - } + if (arguments.length == 0 && BooksWithoutBorders.getConfiguration().getAdminDecrypt() && + player.hasPermission(Permission.ADMIN.toString())) { + return adminDecrypt(player, bookMetadata); } else if (arguments.length == 0) { - BooksWithoutBorders.sendErrorMessage(player, "No decryption password given!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_DECRYPT_MISSING_KEY); return false; } + //Decrypt the book normally String key = EncryptionHelper.getNumberKeyFromStringKey(arguments[0]); - - //Decrypt the book ItemStack book = EncryptionHelper.loadEncryptedBook(player, key, true); if (book != null) { InventoryHelper.setHeldWrittenBook(player, book); - BooksWithoutBorders.sendSuccessMessage(player, "Book decrypted!"); + stringFormatter.displaySuccessMessage(player, Translatable.SUCCESS_DECRYPTED); return true; } else { - BooksWithoutBorders.sendErrorMessage(player, "Failed to decrypt book!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_DECRYPT_FAILED); + return false; + } + } + + /** + * Uses the admin decrypt to decrypt a book without providing the password + * + * @param player

The admin decrypting the book

+ * @param bookMetadata

The metadata of the book to decrypt

+ * @return

True if successful

+ */ + private boolean adminDecrypt(@NotNull Player player, @NotNull BookMeta bookMetadata) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); + File encryptedDirectory = new File(BooksWithoutBorders.getConfiguration().getEncryptedBookPath()); + String[] encryptedFiles = encryptedDirectory.list(); + if (encryptedFiles == null) { + stringFormatter.displayErrorMessage(player, Translatable.ERROR_ENCRYPTED_DIRECTORY_EMPTY_OR_MISSING); + return false; + } + + //Get the "encryption key" from the filename + String key = ""; + for (String encryptedFile : encryptedFiles) { + if (encryptedFile.contains(BookHelper.getBookFile(bookMetadata, player, true))) { + key = encryptedFile.substring(encryptedFile.indexOf("[") + 1, encryptedFile.indexOf("]")); + break; + } + } + + if (!key.equalsIgnoreCase("")) { + //Decrypt the book + ItemStack book = EncryptionHelper.loadEncryptedBook(player, key, false); + if (book != null) { + InventoryHelper.setHeldWrittenBook(player, book); + stringFormatter.displaySuccessMessage(player, Translatable.SUCCESS_AUTO_DECRYPTED); + return true; + } else { + return false; + } + } else { + stringFormatter.displayErrorMessage(player, Translatable.ERROR_ENCRYPTED_BOOK_UNKNOWN); return false; } } @@ -109,9 +117,7 @@ public class CommandDecrypt implements TabExecutor { @NotNull String[] arguments) { int argumentCount = arguments.length; if (argumentCount == 1) { - List info = new ArrayList<>(); - info.add(""); - return info; + return List.of(""); } return new ArrayList<>(); } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java index 475c3b1..0f53d88 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandSave.java @@ -41,7 +41,7 @@ public class CommandSave implements TabExecutor { * @param savePublic

Whether to save the book in the public directory or the player directory

* @return

True if a book was saved successfully

*/ - boolean saveHeldBook(@NotNull CommandSender sender, @NotNull String[] arguments, boolean savePublic) { + protected boolean saveHeldBook(@NotNull CommandSender sender, @NotNull String[] arguments, boolean savePublic) { if (!(sender instanceof Player player)) { BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!"); return false; @@ -83,8 +83,8 @@ public class CommandSave implements TabExecutor { return; } - String savePath = BookHelper.getBookDirectoryPathString( - saveToPublicFolder ? BookDirectory.PUBLIC : BookDirectory.PLAYER, player); + String savePath = BookHelper.getBookDirectoryPathString(saveToPublicFolder ? + BookDirectory.PUBLIC : BookDirectory.PLAYER, player); if (savePath == null) { BooksWithoutBorders.sendErrorMessage(player, "Saving Failed! Unable to find the save path!"); diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java b/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java index 8a42f20..fda1f49 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java @@ -18,6 +18,16 @@ public enum Translatable implements TranslatableMessage { */ SUCCESS_CLEARED, + /** + * The success message displayed when the decrypt command succeeds + */ + SUCCESS_DECRYPTED, + + /** + * The success message displayed when a book is successfully decrypted without providing the key + */ + SUCCESS_AUTO_DECRYPTED, + /** * The error to display when the console attempts to run a player-only command */ @@ -73,6 +83,26 @@ public enum Translatable implements TranslatableMessage { */ ERROR_VAULT_COST_BUT_UNAVAILABLE, + /** + * The error displayed when trying to decrypt a book without displaying the key + */ + ERROR_DECRYPT_MISSING_KEY, + + /** + * The error displayed when failing to decrypt a book for any reason + */ + ERROR_DECRYPT_FAILED, + + /** + * The error displayed when listing all encrypted files returns null + */ + ERROR_ENCRYPTED_DIRECTORY_EMPTY_OR_MISSING, + + /** + * The error displayed when failing to match an encrypted book during admin decrypt + */ + ERROR_ENCRYPTED_BOOK_UNKNOWN, + /** * The header displayed before printing all commands */ diff --git a/src/main/java/net/knarcraft/bookswithoutborders/state/EncryptionStyle.java b/src/main/java/net/knarcraft/bookswithoutborders/state/EncryptionStyle.java index 7a942e7..9491051 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/state/EncryptionStyle.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/state/EncryptionStyle.java @@ -8,7 +8,9 @@ import org.jetbrains.annotations.NotNull; public enum EncryptionStyle { DNA("dna"), - SUBSTITUTION("substitution"); + SUBSTITUTION("substitution"), + AES("aes"), + ; private final String name; diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFormatter.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFormatter.java index 5c218e4..29dbcbb 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFormatter.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFormatter.java @@ -95,8 +95,11 @@ public final class BookFormatter { */ public static void formatLastPageAddNewline(@NotNull List rawPages, int fitsNewline) { int pageIndex = rawPages.size() - 1; - if (rawPages.get(pageIndex).length() <= fitsNewline && !rawPages.get(pageIndex).isEmpty()) { - rawPages.set(pageIndex, (rawPages.get(pageIndex)) + "\n"); + String pageContents = rawPages.get(pageIndex); + if (pageContents == null) { + rawPages.set(pageIndex, ""); + } else if (pageContents.length() <= fitsNewline && !pageContents.isEmpty()) { + rawPages.set(pageIndex, pageContents + "\n"); } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java index 6f152ba..13a75e5 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java @@ -2,6 +2,7 @@ package net.knarcraft.bookswithoutborders.utility; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.BooksWithoutBordersConfig; +import net.knarcraft.bookswithoutborders.encryption.AES; import net.knarcraft.bookswithoutborders.encryption.GenenCrypt; import net.knarcraft.bookswithoutborders.encryption.SubstitutionCipher; import net.knarcraft.bookswithoutborders.state.EncryptionStyle; @@ -74,6 +75,12 @@ public final class EncryptionHelper { encryptedPages.add(sc.encrypt(book.getPage(x + 1), integerKey)); } return encryptedPages; + } else if (style == EncryptionStyle.AES) { + AES aes = new AES(AES.generateIV(), AES.generateIV()); + for (int x = 0; x < book.getPages().size(); x++) { + encryptedPages.add(aes.encryptDecryptText(book.getPage(x + 1), integerKey, true)); + } + return encryptedPages; } else { BooksWithoutBorders.sendErrorMessage(player, "Invalid encryption style encountered!"); return null; diff --git a/src/main/resources/strings.yml b/src/main/resources/strings.yml index 3f40c6f..2a65c2d 100644 --- a/src/main/resources/strings.yml +++ b/src/main/resources/strings.yml @@ -2,6 +2,8 @@ en: PREFIX: "[BwB]" SUCCESS_COPY: "Book copied!" SUCCESS_CLEARED: "Book cleared!" + SUCCESS_DECRYPTED: "Book decrypted!" + SUCCESS_AUTO_DECRYPTED: "Book auto-decrypted!" ERROR_PLAYER_ONLY: "This command can only be used by a player!" ERROR_NOT_HOLDING_WRITTEN_BOOK: "You must be holding a written book to {action} it!" ERROR_NOT_HOLDING_WRITABLE_BOOK: "You must be holding a writable book to {action} it!" @@ -15,6 +17,10 @@ en: ERROR_INVENTORY_FULL: "You need an available slot in your inventory." ERROR_METADATA_MISSING: "Unable to get metadata for the held book!" ERROR_VAULT_COST_BUT_UNAVAILABLE: "&4The cost was set to economy, but Vault is unavailable!" + ERROR_DECRYPT_MISSING_KEY: "No decryption password given!" + ERROR_DECRYPT_FAILED: "Failed to decrypt book!" + ERROR_ENCRYPTED_DIRECTORY_EMPTY_OR_MISSING: "Could not find any encrypted files!" + ERROR_ENCRYPTED_BOOK_UNKNOWN: "No matching encrypted book found!" NEUTRAL_COMMANDS_HEADER: | &e[] denote optional parameters <> denote required parameters