diff --git a/README.md b/README.md index 9e2a13c..4c822e6 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,6 @@ Books without Borders has got your back! - The `/migrateBooks` command allows for easy fixing of old book naming, changing the title author separator (the default changed from `,` to `ยค`, as a comma is a natural character to use in a title), or updating books saved as txt to yml. -- Note that if real encryption is enabled, migrating the books will store them unencrypted (like they used to before - real encryption was implemented) afterward. ### Book formatting diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java index ff33580..396a098 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/translation/Translatable.java @@ -307,6 +307,11 @@ public enum Translatable implements TranslatableMessage { * The error displayed when attempting to change a book's title with a title that's too long */ ERROR_TITLE_LENGTH, + + /** + * The error displayed when attempting to encrypt a book that has an existing encrypted file + */ + ERROR_ENCRYPT_ALREADY_SAVED, ; @Override diff --git a/src/main/java/net/knarcraft/bookswithoutborders/container/EncryptedBook.java b/src/main/java/net/knarcraft/bookswithoutborders/container/EncryptedBook.java new file mode 100644 index 0000000..b38a01c --- /dev/null +++ b/src/main/java/net/knarcraft/bookswithoutborders/container/EncryptedBook.java @@ -0,0 +1,23 @@ +package net.knarcraft.bookswithoutborders.container; + +import net.knarcraft.bookswithoutborders.encryption.AESConfiguration; +import net.knarcraft.bookswithoutborders.encryption.EncryptionStyle; +import org.bukkit.inventory.meta.BookMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * A representation of an encrypted book + * + * @param bookMeta
The book's book meta
+ * @param encryptionStyleThe book's encryption style
+ * @param encryptionKeyThe book's encryption key, or null if admin decrypt is forbidden
+ * @param dataThe encrypted pages of the book
+ * @param aesConfigurationThe AES configuration for the book, or null if not AES encrypted
+ */ +public record EncryptedBook(@NotNull BookMeta bookMeta, @NotNull EncryptionStyle encryptionStyle, + @NotNull String encryptionKey, @NotNull ListThe parent folder the file belongs to
- * @param newNameThe new name of the file
- * @param bookMetaThe metadata of the book to migrate
- * @param oldFileThe old file path, in case it should be deleted
+ * @param parentThe parent folder the file belongs to
+ * @param newNameThe new name of the file
+ * @param oldFileThe old file path, in case it should be deleted
* @returnTrue if successfully saved
*/ - private boolean saveBook(@NotNull File parent, @NotNull String newName, @NotNull BookMeta bookMeta, - @NotNull File oldFile) { - try { - BookToFromTextHelper.bookToYml(parent.getAbsolutePath(), newName, bookMeta); - if (!oldFile.getAbsolutePath().equalsIgnoreCase(new File(parent, newName + ".yml").getAbsolutePath())) { - return oldFile.delete(); - } + private boolean deleteBook(@NotNull File parent, @NotNull String newName, + @NotNull File oldFile) { + if (!oldFile.getAbsolutePath().equalsIgnoreCase(new File(parent, newName + ".yml").getAbsolutePath())) { + return oldFile.delete(); + } else { return true; - } catch (IOException exception) { - BooksWithoutBorders.log(Level.SEVERE, "Failed to save migrated book: " + newName); - return false; } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java index cf1cb39..c429588 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookFileHelper.java @@ -198,6 +198,8 @@ public final class BookFileHelper { String stripped = stripExtensionFromPath(path); if (stripped.contains(separator)) { return stripped.split(separator)[0]; + } else if (stripped.contains(",")) { + return stripped.split(",")[0]; } else { return stripped; } @@ -215,6 +217,8 @@ public final class BookFileHelper { String stripped = stripExtensionFromPath(path); if (stripped.contains(separator)) { return stripped.split(separator)[1]; + } else if (stripped.contains(",")) { + return stripped.split(",")[1]; } else { return BooksWithoutBorders.getStringFormatter().getUnFormattedColoredMessage(Formatting.NEUTRAL_UNKNOWN_AUTHOR); } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java index 54ea3d6..f36d510 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookLoader.java @@ -140,7 +140,6 @@ public final class BookLoader { BookHelper.increaseGeneration(book); book.setAmount(numCopies); - if (!isSigned && book.getItemMeta() != null) { return BookHelper.unsignBook((BookMeta) book.getItemMeta(), book.getAmount()); } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java index e86388b..3f6715d 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java @@ -3,6 +3,7 @@ package net.knarcraft.bookswithoutborders.utility; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.StaticMessage; import net.knarcraft.bookswithoutborders.config.translation.Formatting; +import net.knarcraft.bookswithoutborders.container.EncryptedBook; import net.knarcraft.bookswithoutborders.encryption.AESConfiguration; import net.knarcraft.bookswithoutborders.encryption.EncryptionStyle; import net.knarcraft.knarlib.formatting.StringFormatter; @@ -65,39 +66,43 @@ public final class BookToFromTextHelper { /** * Saves an encrypted book's contents to a .yml file * - * @param pathThe path of the folder to save to. Must end with a slash
- * @param fileNameThe name of the file to load to
- * @param bookMetadataMetadata about the book to save
+ * @param pathThe path of the folder to save to
+ * @param fileNameThe name of the file to load to
+ * @param encryptedBookThe encrypted book to save
* @throws IOExceptionIf unable to save the book
*/ - public static void encryptedBookToYml(@NotNull String path, @NotNull String fileName, @NotNull BookMeta bookMetadata, - @NotNull EncryptionStyle encryptionStyle, @NotNull String encryptionKey, - @Nullable AESConfiguration aesConfiguration) throws IOException { - FileConfiguration bookYml = getBookConfiguration(bookMetadata); + public static void encryptedBookToYml(@NotNull String path, @NotNull String fileName, + @NotNull EncryptedBook encryptedBook) throws IOException { + FileConfiguration bookYml = getBookConfiguration(encryptedBook.bookMeta()); - bookYml.set("Encryption.Style", encryptionStyle.toString()); - bookYml.set("Encryption.Key", encryptionKey); - if (encryptionStyle == EncryptionStyle.AES) { - if (aesConfiguration == null) { + bookYml.set("Encryption.Style", encryptedBook.encryptionStyle().toString()); + bookYml.set("Encryption.Key", encryptedBook.encryptionKey()); + if (encryptedBook.encryptionStyle() == EncryptionStyle.AES) { + if (encryptedBook.aesConfiguration() == null) { throw new IOException("Attempted to save AES encrypted book without supplying a configuration!"); } - bookYml.set("Encryption.AES.IV", EncryptionHelper.bytesToHex(aesConfiguration.iv())); - bookYml.set("Encryption.AES.Salt", EncryptionHelper.bytesToHex(aesConfiguration.salt())); + bookYml.set("Encryption.AES.IV", EncryptionHelper.bytesToHex(encryptedBook.aesConfiguration().iv())); + bookYml.set("Encryption.AES.Salt", EncryptionHelper.bytesToHex(encryptedBook.aesConfiguration().salt())); } - ListMetadata for the loaded book
*/ @Nullable - public static BookMeta encryptedBookFromYml(@NotNull File file, @NotNull BookMeta bookMetadata, - @NotNull String userKey, boolean forceDecrypt) { + public static EncryptedBook encryptedBookFromYml(@NotNull File file, @NotNull BookMeta bookMetadata, + @NotNull String userKey, boolean forceDecrypt) { BookMeta meta; try { @@ -123,25 +128,21 @@ public final class BookToFromTextHelper { return null; } - // If the plaintext is stored in the file, don't bother with real decryption - if (!meta.getPages().isEmpty()) { - return meta; - } - FileConfiguration bookYml = YamlConfiguration.loadConfiguration(file); + + // If key is blank, it's either not real encrypted, or admin decryption is disabled for the book userKey = EncryptionHelper.sha256(userKey); String realKey = bookYml.getString("Encryption.Key", ""); - if (forceDecrypt) { - userKey = realKey; - } - if (!userKey.equals(realKey)) { - return null; + if (!realKey.isBlank()) { + if (forceDecrypt) { + userKey = realKey; + } + if (!userKey.equals(realKey)) { + return null; + } } List