├── test ├── src │ └── test │ │ └── resources │ │ ├── keyfile32 │ │ ├── kdb.key │ │ ├── keyfile64 │ │ ├── issue-38 │ │ └── Database │ │ │ ├── README.md │ │ │ ├── Database.kdbx │ │ │ └── Database.keyx │ │ ├── random_file │ │ ├── test1.kdbx │ │ ├── test123.kdb │ │ ├── test123.kdbx │ │ ├── kdbwithkey.kdb │ │ ├── letter J.jpeg │ │ ├── letter L.jpeg │ │ ├── Attachment.kdbx │ │ ├── V4-AES-AES.kdbx │ │ ├── testDeleted.kdbx │ │ ├── EmptyPassword.kdbx │ │ ├── V3-CustomIcon.kdbx │ │ ├── V4-AES-Argon2.kdbx │ │ ├── V4-CustomIcon.kdbx │ │ ├── issue-70 │ │ ├── test1.kdbx │ │ ├── test2.kdbx │ │ └── test-hugoo10.kdbx │ │ ├── kdbx_hash_test.kdbx │ │ ├── kdbx_keyfile32.kdbx │ │ ├── kdbx_keyfile64.kdbx │ │ ├── Database-4.1-123.kdbx │ │ ├── ExampleDatabase.kdbx │ │ ├── KeyFileDatabase.kdbx │ │ ├── NoPasswordWithKey.kdbx │ │ ├── V4-ChaCha20-AES.kdbx │ │ ├── test123-AES-AES.kdbx │ │ ├── test123-AES-Argon2.kdbx │ │ ├── EmptyPasswordWithKey.kdbx │ │ ├── kdb_with_random_file.kdbx │ │ ├── test123-ChaCha20-AES.kdbx │ │ ├── V4-AES-Argon2-CustomIcon.kdbx │ │ ├── issue-27 │ │ ├── bogus-timestamp.kdbx │ │ └── bogus-timestamp2.kdbx │ │ ├── test123-ChaCha20-Argon2.kdbx │ │ ├── V4-ChaCha20-Argon2-Attachment.kdbx │ │ ├── EmptyPasswordWithKey.key │ │ ├── KeyFileDatabase.key │ │ ├── NoPasswordWithKey.key │ │ ├── kdbx_hash_test.keyx │ │ └── kdbx_hash_test_wrong_hash.keyx └── pom.xml ├── .travis.yml ├── .gitignore ├── all ├── src │ └── main │ │ └── java │ │ └── org │ │ └── linguafranca │ │ └── pwdb │ │ ├── IgnoreMe.java │ │ └── package-info.java └── pom.xml ├── database ├── src │ └── main │ │ └── java │ │ └── org │ │ └── linguafranca │ │ └── pwdb │ │ ├── StreamConfiguration.java │ │ ├── security │ │ ├── KeyDerivationFunction.java │ │ ├── CipherAlgorithm.java │ │ └── ChaCha.java │ │ ├── Icon.java │ │ ├── Credentials.java │ │ ├── protect │ │ └── ProtectedDatabase.java │ │ ├── SerializableDatabase.java │ │ └── StreamFormat.java └── pom.xml ├── jaxb ├── src │ ├── test │ │ └── java │ │ │ └── org │ │ │ └── linguafranca │ │ │ └── pwdb │ │ │ └── kdbx │ │ │ └── jaxb │ │ │ ├── JaxbRecycleBinTest.java │ │ │ ├── JaxbV4LoadTest.java │ │ │ ├── JaxbBasicDatabaseTest.java │ │ │ ├── JaxbLoaderTest.java │ │ │ ├── JaxbSerializableDatabaseTest.java │ │ │ ├── JaxbPropertyValueTest.java │ │ │ ├── JaxbBinaryPropertyV3Test.java │ │ │ ├── JaxbTest.java │ │ │ ├── JaxbBinaryPropertyV4Test.java │ │ │ └── JaxbSaveAndReloadTest.java │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── linguafranca │ │ │ └── pwdb │ │ │ └── kdbx │ │ │ └── jaxb │ │ │ ├── base │ │ │ ├── ValueBinding.java │ │ │ └── AbstractJaxbParentedBinding.java │ │ │ ├── util │ │ │ ├── JaxbUtil.java │ │ │ └── DateAdapter.java │ │ │ └── JaxbIcon.java │ └── generated │ │ └── java │ │ ├── org │ │ └── linguafranca │ │ │ └── pwdb │ │ │ └── kdbx │ │ │ └── jaxb │ │ │ └── binding │ │ │ ├── Adapter2.java │ │ │ ├── Adapter3.java │ │ │ ├── Adapter1.java │ │ │ ├── Parented.java │ │ │ ├── History.java │ │ │ ├── ValueExtender.java │ │ │ └── CustomData.java │ │ └── META-INF │ │ └── sun-jaxb.episode ├── gradle-source-sets.txt └── bindings.xml ├── simple ├── src │ ├── test │ │ └── java │ │ │ └── org │ │ │ └── linguafranca │ │ │ └── pwdb │ │ │ └── kdbx │ │ │ └── simple │ │ │ ├── SimpleRecycleBinTest.java │ │ │ ├── SimpleDatabaseTest.java │ │ │ ├── SimpleDatabaseLoaderTest.java │ │ │ ├── SimplePropertyValueTest.java │ │ │ ├── SimpleBinaryPropertyV4Test.java │ │ │ └── SimpleBinaryPropertyV3Test.java │ └── main │ │ └── java │ │ └── org │ │ └── linguafranca │ │ └── pwdb │ │ └── kdbx │ │ └── simple │ │ ├── converter │ │ ├── KeePassBooleanConverter.java │ │ ├── EmptyStringConverter.java │ │ ├── TimeConverter.java │ │ ├── UuidConverter.java │ │ ├── Base64ByteArrayConverter.java │ │ └── ValueConverter.java │ │ └── SimpleIcon.java └── pom.xml ├── dom ├── src │ ├── test │ │ └── java │ │ │ └── org │ │ │ └── linguafranca │ │ │ └── pwdb │ │ │ └── kdbx │ │ │ └── dom │ │ │ ├── DomRecycleBinTest.java │ │ │ ├── DomV4Test.java │ │ │ ├── DomHelperTest.java │ │ │ ├── DomDatabaseWrapperLoaderTest.java │ │ │ ├── DomPropertyValueTest.java │ │ │ ├── DomBinaryPropertyV3Test.java │ │ │ ├── DomBinaryPropertyV4Test.java │ │ │ ├── DomDatabaseWrapperTest.java │ │ │ └── DomSaveAndReloadTest.java │ └── main │ │ └── java │ │ └── org │ │ └── linguafranca │ │ └── pwdb │ │ └── kdbx │ │ └── dom │ │ └── DomIconWrapper.java └── pom.xml ├── bitbucket-pipelines.yml ├── logback.xml ├── util ├── src │ └── main │ │ └── java │ │ └── org │ │ └── linguafranca │ │ └── test │ │ ├── util │ │ ├── TestUtil.java │ │ └── HexViewer.java │ │ └── maven │ │ └── MavenRunListener.java └── pom.xml ├── kdb ├── src │ ├── test │ │ └── java │ │ │ └── org │ │ │ └── linguafranca │ │ │ └── pwdb │ │ │ └── kdb │ │ │ ├── KeyFileTest.java │ │ │ ├── KdbSerializerTest.java │ │ │ ├── KdbDatabaseLoaderTest.java │ │ │ └── KdbDatabaseTest.java │ └── main │ │ └── java │ │ └── org │ │ └── linguafranca │ │ └── pwdb │ │ └── kdb │ │ ├── KdbIcon.java │ │ └── KdbCredentials.java └── pom.xml ├── jackson ├── src │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── linguafranca │ │ │ └── pwdb │ │ │ └── kdbx │ │ │ └── jackson │ │ │ ├── converter │ │ │ ├── Base64ToByteConverter.java │ │ │ ├── ByteToBase64Converter.java │ │ │ ├── StringToBooleanConverter.java │ │ │ ├── BooleanToStringConverter.java │ │ │ ├── UUIDToBase64Converter.java │ │ │ ├── DateToStringConverter.java │ │ │ ├── Base64ToUUIDConverter.java │ │ │ ├── StringToDateConverter.java │ │ │ ├── ValueSerializer.java │ │ │ └── ValueDeserializer.java │ │ │ ├── JacksonHistory.java │ │ │ └── JacksonIcon.java │ └── test │ │ └── java │ │ └── org │ │ └── linguafranca │ │ └── pwdb │ │ ├── JacksonRecycleBinTest.java │ │ ├── JacksonDatabaseTest.java │ │ ├── JacksonDatabaseLoaderTest.java │ │ ├── JacksonPropertyValueTest.java │ │ ├── JacksonBinaryPropertyV3Test.java │ │ ├── JacksonBinaryPropertyV4Test.java │ │ ├── JacksonDatabaseLoadTest.java │ │ └── JacksonSaveAndReloadTest.java └── pom.xml ├── example ├── src │ ├── test │ │ └── java │ │ │ └── org │ │ │ └── linguafranca │ │ │ └── pwdb │ │ │ └── kdbx │ │ │ ├── validation │ │ │ ├── Issue38Test.java │ │ │ ├── Issue70Test.java │ │ │ ├── Issue27Test.java │ │ │ └── Issue33Test.java │ │ │ ├── SaxParseTest.java │ │ │ └── UtilTest.java │ └── main │ │ └── java │ │ └── org │ │ └── linguafranca │ │ └── pwdb │ │ ├── example │ │ └── SecureCharBufferPropertyValue.java │ │ └── kdbx │ │ └── ChooseFile.java └── pom.xml ├── kdbx ├── pom.xml └── src │ ├── test │ └── java │ │ └── org │ │ └── linguafranca │ │ └── pwdb │ │ ├── kdbx │ │ ├── HelperTest.java │ │ └── HelpersTest.java │ │ └── security │ │ └── StreamEncryptionTest.java │ └── main │ └── java │ └── org │ └── linguafranca │ └── pwdb │ ├── hashedblock │ ├── CollectingOutputStream.java │ └── CollectingInputStream.java │ └── kdbx │ └── KdbxCreds.java └── .circleci └── config.yml /test/src/test/resources/keyfile32: -------------------------------------------------------------------------------- 1 | KQQWFvUqScAobSfwq4z5MwnbITIb38vm -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: openjdk7 3 | script: mvn clean test 4 | -------------------------------------------------------------------------------- /test/src/test/resources/kdb.key: -------------------------------------------------------------------------------- 1 | a320d61f69f0903d9f4cecb95c81b35f77b1af232a0b8f2d84377f7df57022d4 -------------------------------------------------------------------------------- /test/src/test/resources/keyfile64: -------------------------------------------------------------------------------- 1 | bc63a755436af06b88027816446ba0486e8e15fac0e26dbaee82f662c77546bc -------------------------------------------------------------------------------- /test/src/test/resources/issue-38/Database/README.md: -------------------------------------------------------------------------------- 1 | This was rasied as Issue 38 - Keyfile is version 2, which was not supported. -------------------------------------------------------------------------------- /test/src/test/resources/random_file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/random_file -------------------------------------------------------------------------------- /test/src/test/resources/test1.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/test1.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/test123.kdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/test123.kdb -------------------------------------------------------------------------------- /test/src/test/resources/test123.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/test123.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/kdbwithkey.kdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/kdbwithkey.kdb -------------------------------------------------------------------------------- /test/src/test/resources/letter J.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/letter J.jpeg -------------------------------------------------------------------------------- /test/src/test/resources/letter L.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/letter L.jpeg -------------------------------------------------------------------------------- /test/src/test/resources/Attachment.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/Attachment.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/V4-AES-AES.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/V4-AES-AES.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/testDeleted.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/testDeleted.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/EmptyPassword.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/EmptyPassword.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/V3-CustomIcon.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/V3-CustomIcon.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/V4-AES-Argon2.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/V4-AES-Argon2.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/V4-CustomIcon.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/V4-CustomIcon.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/issue-70/test1.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/issue-70/test1.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/issue-70/test2.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/issue-70/test2.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/kdbx_hash_test.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/kdbx_hash_test.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/kdbx_keyfile32.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/kdbx_keyfile32.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/kdbx_keyfile64.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/kdbx_keyfile64.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/Database-4.1-123.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/Database-4.1-123.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/ExampleDatabase.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/ExampleDatabase.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/KeyFileDatabase.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/KeyFileDatabase.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/NoPasswordWithKey.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/NoPasswordWithKey.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/V4-ChaCha20-AES.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/V4-ChaCha20-AES.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/test123-AES-AES.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/test123-AES-AES.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/test123-AES-Argon2.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/test123-AES-Argon2.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/EmptyPasswordWithKey.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/EmptyPasswordWithKey.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/issue-70/test-hugoo10.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/issue-70/test-hugoo10.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/kdb_with_random_file.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/kdb_with_random_file.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/test123-ChaCha20-AES.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/test123-ChaCha20-AES.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/V4-AES-Argon2-CustomIcon.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/V4-AES-Argon2-CustomIcon.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/issue-27/bogus-timestamp.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/issue-27/bogus-timestamp.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/test123-ChaCha20-Argon2.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/test123-ChaCha20-Argon2.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/issue-27/bogus-timestamp2.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/issue-27/bogus-timestamp2.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/issue-38/Database/Database.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/issue-38/Database/Database.kdbx -------------------------------------------------------------------------------- /test/src/test/resources/V4-ChaCha20-Argon2-Attachment.kdbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jorabin/KeePassJava2/HEAD/test/src/test/resources/V4-ChaCha20-Argon2-Attachment.kdbx -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | testOutput 2 | build 3 | .vscode/* 4 | *.versionsBackup 5 | **/target 6 | 7 | #settings.gradle 8 | #gradlew 9 | #gradlew.bat 10 | #.gradle 11 | #gradle 12 | #build.gradle 13 | 14 | -------------------------------------------------------------------------------- /all/src/main/java/org/linguafranca/pwdb/IgnoreMe.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb; 2 | 3 | /** 4 | * This is here for Javadoc generation purposes only 5 | */ 6 | public class IgnoreMe { 7 | } 8 | -------------------------------------------------------------------------------- /test/src/test/resources/EmptyPasswordWithKey.key: -------------------------------------------------------------------------------- 1 | 1.00Vevc5pI13VSR11q74seXQkKJrccSkjnNZ6cfFBYhvpk= 2 | -------------------------------------------------------------------------------- /test/src/test/resources/KeyFileDatabase.key: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.00 5 | 6 | 7 | uE9L7SGiT0+PrSvZ0oIzaLjtpsiu50ciR/JXc44Pw24= 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/src/test/resources/NoPasswordWithKey.key: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.00 5 | 6 | 7 | RJS69T/8tKYwO/fXPNGdtHlgLM5VfJmBDQLOlsg1AcE= 8 | 9 | 10 | -------------------------------------------------------------------------------- /database/src/main/java/org/linguafranca/pwdb/StreamConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb; 2 | 3 | /** 4 | * A marker interface for KdbxHeader and similar, if there ever is one 5 | */ 6 | public interface StreamConfiguration { 7 | class None implements StreamConfiguration { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/src/test/resources/kdbx_hash_test.keyx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.0 5 | 6 | 7 | 8 | 66F110CA E32995B5 EFA8E672 1E70C773 9 | 48F8E260 EEDD8744 93F41803 5BFDC27D 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/src/test/resources/issue-38/Database/Database.keyx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.0 5 | 6 | 7 | 8 | A700DD37 8EBAABE2 1936E1F9 9FED8DEE 9 | D0F71664 B25B0DD2 961FFDA6 9E194E75 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/src/test/resources/kdbx_hash_test_wrong_hash.keyx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.0 5 | 6 | 7 | 8 | 66F110CA E32995B5 EFA8E672 1E70C773 9 | 48F8E260 EEDD8744 93F41803 5BFDC27D 10 | 11 | 12 | -------------------------------------------------------------------------------- /jaxb/src/test/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbRecycleBinTest.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.jaxb; 2 | 3 | import org.linguafranca.pwdb.checks.RecycleBinChecks; 4 | 5 | /** 6 | * @author jo 7 | */ 8 | public class JaxbRecycleBinTest extends RecycleBinChecks { 9 | public JaxbRecycleBinTest() { 10 | database = new JaxbDatabase(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /jaxb/gradle-source-sets.txt: -------------------------------------------------------------------------------- 1 | sourceSets { 2 | main { 3 | java { 4 | srcDirs = ['src/main/java', 'src/generated/java'] 5 | } 6 | resources { 7 | srcDirs = ['src/main/resources'] 8 | } 9 | } 10 | test{ 11 | java { 12 | srcDirs = ['src/test/java'] 13 | } 14 | resources { 15 | srcDirs = ['src/test/resources'] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /simple/src/test/java/org/linguafranca/pwdb/kdbx/simple/SimpleRecycleBinTest.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.simple; 2 | 3 | import org.linguafranca.pwdb.checks.RecycleBinChecks; 4 | 5 | /** 6 | * @author jo 7 | */ 8 | public class SimpleRecycleBinTest extends RecycleBinChecks { 9 | public SimpleRecycleBinTest() { 10 | database = new SimpleDatabase(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dom/src/test/java/org/linguafranca/pwdb/kdbx/dom/DomRecycleBinTest.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.dom; 2 | 3 | import org.linguafranca.pwdb.checks.RecycleBinChecks; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * @author jo 9 | */ 10 | public class DomRecycleBinTest extends RecycleBinChecks { 11 | public DomRecycleBinTest() throws IOException { 12 | database = new DomDatabaseWrapper(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /all/src/main/java/org/linguafranca/pwdb/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This module provides a simple import of the database implementations of KeePass, "all" in the diagram below. 3 | *

4 | * 5 | *

6 | * @see Module Structure 7 | * in the readme at GitHub for a discussion of the project modules and links to JavaDocs. 8 | */ 9 | package org.linguafranca.pwdb; -------------------------------------------------------------------------------- /bitbucket-pipelines.yml: -------------------------------------------------------------------------------- 1 | # This is a sample build configuration for Java (Maven). 2 | # Check our guides at https://confluence.atlassian.com/x/zd-5Mw for more examples. 3 | # Only use spaces to indent your .yml configuration. 4 | # ----- 5 | # You can specify a custom docker image from Docker Hub as your build environment. 6 | image: maven:3.5.2-jdk-7 7 | 8 | pipelines: 9 | #only on this branch 10 | bitbucket-build: 11 | - step: 12 | caches: 13 | - maven 14 | script: # Modify the commands below to build your repository. 15 | - mvn -B verify # -B batch mode makes Maven less verbose -------------------------------------------------------------------------------- /logback.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 9 | 10 | -%highlight(%-5level) %d{HH:mm:ss.SSS} [%thread] %logger{36} - %cyan(%marker) %msg%n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 100 20 | 21 | -------------------------------------------------------------------------------- /jaxb/src/main/java/org/linguafranca/pwdb/kdbx/jaxb/base/ValueBinding.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.jaxb.base; 2 | 3 | import javax.xml.bind.annotation.XmlAccessType; 4 | import javax.xml.bind.annotation.XmlAccessorType; 5 | import javax.xml.bind.annotation.XmlTransient; 6 | import javax.xml.bind.annotation.XmlValue; 7 | 8 | /** 9 | * Ancestor class of StringField.Value, providing a way of flagging protection 10 | * separate from @Protected and @ProtectInMemory 11 | */ 12 | @XmlAccessorType(XmlAccessType.FIELD) 13 | public abstract class ValueBinding { 14 | 15 | @XmlTransient 16 | public boolean protectOnOutput; 17 | 18 | @XmlValue 19 | public String value; 20 | 21 | public String getValue(){ 22 | return value; 23 | } 24 | 25 | public void setValue(String string){ 26 | value = string; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /util/src/main/java/org/linguafranca/test/util/TestUtil.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.test.util; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.io.PrintStream; 6 | 7 | public class TestUtil { 8 | /** 9 | * Do nothing output stream 10 | */ 11 | public static class NullOutputStream extends OutputStream { 12 | 13 | @Override 14 | public void write(int b) throws IOException { 15 | 16 | } 17 | } 18 | /** 19 | * set system property to suppress output from tests 20 | * @return if "inhibitConsoleOutput" has been set, e.g. in a profile 21 | */ 22 | public static PrintStream getTestPrintStream() { 23 | return Boolean.getBoolean("inhibitConsoleOutput") ? 24 | new PrintStream(new NullOutputStream()) : 25 | new PrintStream(System.out); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /kdb/src/test/java/org/linguafranca/pwdb/kdb/KeyFileTest.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdb; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | /** 11 | * @author jo 12 | */ 13 | public class KeyFileTest { 14 | 15 | @Test 16 | public void openKdbWithKeyFile() throws IOException { 17 | InputStream key = getClass().getClassLoader().getResourceAsStream("kdb.key"); 18 | KdbCredentials creds = new KdbCredentials.KeyFile("123".getBytes(), key); 19 | InputStream is = getClass().getClassLoader().getResourceAsStream("kdbwithkey.kdb"); 20 | KdbDatabase db = KdbDatabase.load(creds, is); 21 | assertEquals(1, db.getRootGroup().getGroupsCount()); 22 | assertEquals("General", db.getRootGroup().getGroups().get(0).getName()); 23 | } 24 | } -------------------------------------------------------------------------------- /util/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.linguafranca.pwdb 8 | KeePassJava2-parent 9 | 2.2.4 10 | 11 | 12 | PWDB :: Util 13 | Some underlying utilities which are needed for running tests. 14 | util 15 | 16 | 17 | true 18 | 19 | 20 | 21 | 22 | junit 23 | junit 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /jaxb/src/generated/java/org/linguafranca/pwdb/kdbx/jaxb/binding/Adapter2.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 3 | // See http://java.sun.com/xml/jaxb 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2023.05.17 at 11:23:19 AM BST 6 | // 7 | 8 | 9 | package org.linguafranca.pwdb.kdbx.jaxb.binding; 10 | 11 | import javax.xml.bind.annotation.adapters.XmlAdapter; 12 | 13 | public class Adapter2 14 | extends XmlAdapter 15 | { 16 | 17 | 18 | public Boolean unmarshal(String value) { 19 | return (org.linguafranca.pwdb.kdbx.Helpers.toBoolean(value)); 20 | } 21 | 22 | public String marshal(Boolean value) { 23 | return (org.linguafranca.pwdb.kdbx.Helpers.fromBoolean(value)); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /database/src/main/java/org/linguafranca/pwdb/security/KeyDerivationFunction.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.security; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Interface defining a Key Derivation Function 7 | */ 8 | public interface KeyDerivationFunction { 9 | /** 10 | * The UUID of this key derivation function 11 | */ 12 | UUID getKdfUuid(); 13 | 14 | /** 15 | * Transform a key using this key derivation function 16 | * 17 | * @param key the key to transform 18 | * @param transformParams the parameters defining the way the transformation is to be carried out 19 | * @return a transformed key 20 | */ 21 | byte[] getTransformedKey(byte[] key, VariantDictionary transformParams); 22 | 23 | /** 24 | * Create default KDF parameters 25 | */ 26 | VariantDictionary createKdfParameters(); 27 | 28 | /** 29 | * Get a name 30 | */ 31 | String getName(); 32 | } 33 | -------------------------------------------------------------------------------- /jaxb/src/generated/java/org/linguafranca/pwdb/kdbx/jaxb/binding/Adapter3.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 3 | // See http://java.sun.com/xml/jaxb 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2023.05.17 at 11:23:19 AM BST 6 | // 7 | 8 | 9 | package org.linguafranca.pwdb.kdbx.jaxb.binding; 10 | 11 | import java.util.UUID; 12 | import javax.xml.bind.annotation.adapters.XmlAdapter; 13 | 14 | public class Adapter3 15 | extends XmlAdapter 16 | { 17 | 18 | 19 | public UUID unmarshal(String value) { 20 | return (org.linguafranca.pwdb.kdbx.Helpers.uuidFromBase64(value)); 21 | } 22 | 23 | public String marshal(UUID value) { 24 | return (org.linguafranca.pwdb.kdbx.Helpers.base64FromUuid(value)); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /jaxb/src/generated/java/org/linguafranca/pwdb/kdbx/jaxb/binding/Adapter1.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 3 | // See http://java.sun.com/xml/jaxb 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2023.05.17 at 11:23:19 AM BST 6 | // 7 | 8 | 9 | package org.linguafranca.pwdb.kdbx.jaxb.binding; 10 | 11 | import java.util.Date; 12 | import javax.xml.bind.annotation.adapters.XmlAdapter; 13 | 14 | public class Adapter1 15 | extends XmlAdapter 16 | { 17 | 18 | 19 | public Date unmarshal(String value) { 20 | return (org.linguafranca.pwdb.kdbx.jaxb.util.DateAdapter.fromString(value)); 21 | } 22 | 23 | public String marshal(Date value) { 24 | return (org.linguafranca.pwdb.kdbx.jaxb.util.DateAdapter.toString(value)); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /util/src/main/java/org/linguafranca/test/util/HexViewer.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.test.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.PrintStream; 6 | 7 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 8 | 9 | /** 10 | * Useful for e.g. viewing the raw file contents 11 | */ 12 | public class HexViewer { 13 | 14 | static PrintStream printStream = getTestPrintStream(); 15 | 16 | public static void list(InputStream is) throws IOException { 17 | for (int i = 0; i < 32; i++) { 18 | byte[] buf = new byte [16]; 19 | is.read(buf); 20 | StringBuilder sb = new StringBuilder(); 21 | for (byte b: buf) { 22 | sb.append(String.format("%02X ", b)); 23 | } 24 | sb.append(" "); 25 | for (byte b : buf) { 26 | sb.append(b < 0x20 || b > 0x7e ? (char) 0x00B7 : (char) b); 27 | } 28 | printStream.println(sb); 29 | } 30 | } 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /database/src/main/java/org/linguafranca/pwdb/Icon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb; 18 | 19 | /** 20 | * Interface for icons. 21 | * 22 | *

Intended as a point of flexibility, at some point this 23 | * may get embellished to allow custom icons and retrieval 24 | * of icon assets and so on. 25 | * 26 | * @author Jo 27 | */ 28 | public interface Icon { 29 | int getIndex(); 30 | 31 | void setIndex(int index); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/converter/Base64ToByteConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jackson.converter; 18 | 19 | import java.util.Base64; 20 | 21 | import com.fasterxml.jackson.databind.util.StdConverter; 22 | 23 | public class Base64ToByteConverter extends StdConverter { 24 | 25 | @Override 26 | public byte[] convert(String value) { 27 | return Base64.getDecoder().decode(value); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/converter/ByteToBase64Converter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb.kdbx.jackson.converter; 17 | 18 | import java.util.Base64; 19 | 20 | import com.fasterxml.jackson.databind.util.StdConverter; 21 | 22 | public class ByteToBase64Converter extends StdConverter { 23 | 24 | @Override 25 | public String convert(byte[] value) { 26 | return new String(Base64.getEncoder().encode(value)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /jaxb/src/main/java/org/linguafranca/pwdb/kdbx/jaxb/base/AbstractJaxbParentedBinding.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jaxb.base; 18 | 19 | import javax.xml.bind.annotation.XmlTransient; 20 | 21 | /** 22 | * Ancestor class for Entry and Group Jaxb Bindings, allowing insertion of 23 | * a reference to the parent group. 24 | * 25 | * @author jo 26 | */ 27 | public abstract class AbstractJaxbParentedBinding { 28 | @XmlTransient 29 | public AbstractJaxbParentedBinding parent; 30 | } 31 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/converter/StringToBooleanConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb.kdbx.jackson.converter; 17 | 18 | import org.linguafranca.pwdb.kdbx.Helpers; 19 | 20 | import com.fasterxml.jackson.databind.util.StdConverter; 21 | 22 | public class StringToBooleanConverter extends StdConverter{ 23 | 24 | @Override 25 | public Boolean convert(String value) { 26 | return Helpers.toBoolean(value); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/converter/BooleanToStringConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jackson.converter; 18 | 19 | import org.linguafranca.pwdb.kdbx.Helpers; 20 | 21 | import com.fasterxml.jackson.databind.util.StdConverter; 22 | 23 | public class BooleanToStringConverter extends StdConverter { 24 | 25 | @Override 26 | public String convert(Boolean value) { 27 | return Helpers.fromBoolean(value); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/converter/UUIDToBase64Converter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb.kdbx.jackson.converter; 17 | 18 | import java.util.UUID; 19 | 20 | import org.linguafranca.pwdb.kdbx.Helpers; 21 | 22 | import com.fasterxml.jackson.databind.util.StdConverter; 23 | 24 | public class UUIDToBase64Converter extends StdConverter { 25 | 26 | @Override 27 | public String convert(UUID value) { 28 | return Helpers.base64FromUuid(value); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/converter/DateToStringConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jackson.converter; 18 | 19 | import java.util.Date; 20 | 21 | import org.linguafranca.pwdb.kdbx.Helpers; 22 | 23 | import com.fasterxml.jackson.databind.util.StdConverter; 24 | 25 | public class DateToStringConverter extends StdConverter { 26 | 27 | @Override 28 | public String convert(Date date) { 29 | return Helpers.fromDate(date); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /dom/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | KeePassJava2-parent 5 | org.linguafranca.pwdb 6 | 2.2.4 7 | ../pom.xml 8 | 9 | 4.0.0 10 | 11 | KeePassJava2-dom 12 | KeePassJava2 :: DOM 13 | 14 | 15 | 16 | org.linguafranca.pwdb 17 | KeePassJava2-kdbx 18 | ${project.version} 19 | 20 | 21 | org.linguafranca.pwdb 22 | test 23 | ${project.version} 24 | test-jar 25 | test 26 | 27 | 28 | -------------------------------------------------------------------------------- /jackson/src/test/java/org/linguafranca/pwdb/JacksonRecycleBinTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb; 17 | 18 | import org.linguafranca.pwdb.checks.RecycleBinChecks; 19 | import org.linguafranca.pwdb.kdbx.jackson.JacksonDatabase; 20 | 21 | public class JacksonRecycleBinTest extends RecycleBinChecks { 22 | 23 | public JacksonRecycleBinTest() { 24 | try { 25 | database = new JacksonDatabase(); 26 | } catch(Exception e) { 27 | e.printStackTrace(); 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /jaxb/src/test/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbV4LoadTest.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.jaxb; 2 | 3 | import org.junit.Test; 4 | import org.linguafranca.pwdb.Entry; 5 | import org.linguafranca.pwdb.Visitor; 6 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 7 | 8 | import java.io.InputStream; 9 | import java.io.PrintStream; 10 | 11 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 12 | 13 | /** 14 | * @author jo 15 | */ 16 | public class JaxbV4LoadTest { 17 | 18 | static PrintStream printStream = getTestPrintStream(); 19 | 20 | @Test 21 | public void loadKdbxV4() throws Exception { 22 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("V4-AES-Argon2.kdbx"); 23 | JaxbDatabase database = JaxbDatabase.load(new KdbxCreds("123".getBytes()), inputStream); 24 | database.visit(new Visitor.Print(printStream)); 25 | // test what happens to dates in V4 26 | database.visit(new Visitor.Default(){ 27 | @Override 28 | public void visit(Entry entry) { 29 | printStream.println(entry.getCreationTime()); 30 | } 31 | }); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /jaxb/src/generated/java/org/linguafranca/pwdb/kdbx/jaxb/binding/Parented.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 3 | // See http://java.sun.com/xml/jaxb 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2023.05.17 at 11:23:19 AM BST 6 | // 7 | 8 | 9 | package org.linguafranca.pwdb.kdbx.jaxb.binding; 10 | 11 | import javax.xml.bind.annotation.XmlAccessType; 12 | import javax.xml.bind.annotation.XmlAccessorType; 13 | import javax.xml.bind.annotation.XmlSeeAlso; 14 | import javax.xml.bind.annotation.XmlType; 15 | 16 | 17 | /** 18 | * This class, while generated, is not used see {@link 19 | * org.linguafranca.pwdb.kdbx.jaxb.org.linguafranca.pwdb.base.AbstractJaxbParentedBinding} which is the 20 | * actual implementation class. 21 | * 22 | * 23 | * 24 | */ 25 | @XmlAccessorType(XmlAccessType.FIELD) 26 | @XmlType(name = "Parented") 27 | @XmlSeeAlso({ 28 | JaxbGroupBinding.class, 29 | JaxbEntryBinding.class 30 | }) 31 | public abstract class Parented { 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /jaxb/src/test/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbBasicDatabaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jaxb; 18 | 19 | import org.linguafranca.pwdb.checks.BasicDatabaseChecks; 20 | import org.linguafranca.pwdb.Database; 21 | 22 | import java.io.IOException; 23 | 24 | /** 25 | * @author jo 26 | */ 27 | public class JaxbBasicDatabaseTest extends BasicDatabaseChecks { 28 | 29 | public JaxbBasicDatabaseTest() throws IOException { 30 | } 31 | 32 | @Override 33 | public Database createDatabase() { 34 | return new JaxbDatabase(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /jackson/src/test/java/org/linguafranca/pwdb/JacksonDatabaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb; 17 | 18 | import java.io.IOException; 19 | 20 | import org.linguafranca.pwdb.checks.BasicDatabaseChecks; 21 | import org.linguafranca.pwdb.kdbx.jackson.JacksonDatabase; 22 | 23 | public class JacksonDatabaseTest extends BasicDatabaseChecks { 24 | 25 | public JacksonDatabaseTest() throws IOException { 26 | 27 | } 28 | 29 | 30 | @Override 31 | public Database createDatabase() throws IOException { 32 | return new JacksonDatabase(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /kdb/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | KeePassJava2-parent 5 | org.linguafranca.pwdb 6 | 2.2.4 7 | ../pom.xml 8 | 9 | 4.0.0 10 | 11 | KeePassJava2-kdb 12 | KeePassJava2 :: KDB 13 | Contains an implementation that can load KDB files. 14 | 15 | 16 | 17 | org.linguafranca.pwdb 18 | database 19 | ${project.version} 20 | 21 | 22 | org.linguafranca.pwdb 23 | test 24 | ${project.version} 25 | test-jar 26 | test 27 | 28 | 29 | -------------------------------------------------------------------------------- /database/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | KeePassJava2-parent 5 | org.linguafranca.pwdb 6 | 2.2.4 7 | ../pom.xml 8 | 9 | 4.0.0 10 | 11 | database 12 | PWDB :: Database 13 | Contains root definitions of PWDB Databases etc. 14 | 15 | 16 | 17 | com.google.guava 18 | guava 19 | 20 | 21 | org.bouncycastle 22 | bcpkix-jdk18on 23 | 24 | 25 | org.linguafranca.pwdb 26 | util 27 | ${project.version} 28 | 29 | 30 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/converter/Base64ToUUIDConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jackson.converter; 18 | 19 | import java.util.UUID; 20 | 21 | import org.linguafranca.pwdb.kdbx.Helpers; 22 | 23 | import com.fasterxml.jackson.databind.util.StdConverter; 24 | 25 | public class Base64ToUUIDConverter extends StdConverter { 26 | 27 | @Override 28 | public UUID convert(String value) { 29 | if(value == null || value.isEmpty()) { 30 | return UUID.randomUUID(); 31 | } 32 | return Helpers.uuidFromBase64(value); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /dom/src/test/java/org/linguafranca/pwdb/kdbx/dom/DomV4Test.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.dom; 2 | 3 | import org.junit.Test; 4 | import org.linguafranca.pwdb.Visitor; 5 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 6 | 7 | import java.io.InputStream; 8 | import java.io.PrintStream; 9 | 10 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 11 | 12 | /** 13 | * @author jo 14 | */ 15 | public class DomV4Test { 16 | 17 | static PrintStream printStream = getTestPrintStream(); 18 | 19 | @Test 20 | public void loadKdbxV4() throws Exception { 21 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("V4-AES-Argon2.kdbx"); 22 | DomDatabaseWrapper database = DomDatabaseWrapper.load(new KdbxCreds("123".getBytes()), inputStream); 23 | database.visit(new Visitor.Print(printStream)); 24 | // test what happens to dates in V4 25 | database.visit(new Visitor.Default(){ 26 | 27 | @Override 28 | public void visit(DomEntryWrapper entry) { 29 | printStream.println(entry.getCreationTime()); 30 | } 31 | }); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /jaxb/src/main/java/org/linguafranca/pwdb/kdbx/jaxb/util/JaxbUtil.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.jaxb.util; 2 | 3 | import javax.xml.bind.JAXBContext; 4 | import javax.xml.bind.JAXBElement; 5 | import javax.xml.bind.JAXBException; 6 | import javax.xml.bind.util.JAXBSource; 7 | import javax.xml.namespace.QName; 8 | 9 | public class JaxbUtil { 10 | 11 | // https://stackoverflow.com/questions/879453/how-to-make-a-deep-copy-of-jaxb-object-like-xmlbean-xmlobject-copy 12 | // however it does not copy transients which we need it to, so we don't use it 13 | public static T deepCopyJAXB(T object, Class clazz) { 14 | try { 15 | JAXBContext jaxbContext = JAXBContext.newInstance(clazz); 16 | JAXBElement contentObject = new JAXBElement(new QName(clazz.getSimpleName()), clazz, object); 17 | JAXBSource source = new JAXBSource(jaxbContext, contentObject); 18 | return jaxbContext.createUnmarshaller().unmarshal(source, clazz).getValue(); 19 | } catch (JAXBException e) { 20 | throw new RuntimeException(e); 21 | } 22 | } 23 | 24 | public static T deepCopyJAXB(T object) { 25 | if(object==null) throw new RuntimeException("Can't guess at class"); 26 | return deepCopyJAXB(object, (Class) object.getClass()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /simple/src/test/java/org/linguafranca/pwdb/kdbx/simple/SimpleDatabaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.simple; 18 | 19 | import org.linguafranca.pwdb.checks.BasicDatabaseChecks; 20 | import org.linguafranca.pwdb.Database; 21 | 22 | import java.io.IOException; 23 | 24 | /** 25 | * @author jo 26 | */ 27 | public class SimpleDatabaseTest extends BasicDatabaseChecks { 28 | 29 | public SimpleDatabaseTest() throws IOException { 30 | } 31 | 32 | @Override 33 | public Database createDatabase() { 34 | try { 35 | return new SimpleDatabase(); 36 | } catch (Exception e) { 37 | throw new IllegalStateException(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /jaxb/src/main/java/org/linguafranca/pwdb/kdbx/jaxb/util/DateAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jaxb.util; 18 | 19 | import org.linguafranca.pwdb.kdbx.Helpers; 20 | 21 | import java.util.Date; 22 | 23 | /** 24 | * Used for loading the database template which contains placeholders. 25 | * @author jo 26 | */ 27 | public class DateAdapter { 28 | public static String toString(Date date) { 29 | return Helpers.fromDate(date); 30 | } 31 | 32 | public static Date fromString(String string) { 33 | // this is found in the base template 34 | if (string.equals("${creationDate}")) { 35 | return new Date(); 36 | } 37 | return Helpers.toDate(string); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /database/src/main/java/org/linguafranca/pwdb/security/CipherAlgorithm.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.security; 2 | 3 | import java.io.InputStream; 4 | import java.io.OutputStream; 5 | import java.util.UUID; 6 | 7 | /** 8 | * Interface defining an algorithm for encrypting and decrypting database contents 9 | */ 10 | public interface CipherAlgorithm { 11 | /** 12 | * Returns the UUID of this algorithm 13 | */ 14 | UUID getCipherUuid(); 15 | 16 | /** 17 | * Return the name of this algorithm 18 | */ 19 | String getName(); 20 | 21 | /** 22 | * Create a decrypted stream from the supplied encrypted one 23 | * 24 | * @param encryptedInputStream an encrypted stream 25 | * @param key the decryption key 26 | * @param iv the iv 27 | * @return an unencrypted stream 28 | */ 29 | InputStream getDecryptedInputStream(InputStream encryptedInputStream, byte[] key, byte[] iv); 30 | 31 | /** 32 | * Create an encrypted stream from the supplied unencrypted one 33 | * 34 | * @param decryptedOutputStream an unencrypted stream 35 | * @param key a key 36 | * @param iv an iv 37 | * @return an encrypted stream 38 | */ 39 | OutputStream getEncryptedOutputStream(OutputStream decryptedOutputStream, byte[] key, byte[] iv); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /jackson/src/test/java/org/linguafranca/pwdb/JacksonDatabaseLoaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb; 17 | 18 | import java.io.InputStream; 19 | 20 | import org.linguafranca.pwdb.checks.DatabaseLoaderChecks; 21 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 22 | import org.linguafranca.pwdb.kdbx.jackson.JacksonDatabase; 23 | 24 | public class JacksonDatabaseLoaderTest extends DatabaseLoaderChecks{ 25 | 26 | 27 | public JacksonDatabaseLoaderTest() throws Exception{ 28 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test123.kdbx"); 29 | // file has password credentials 30 | Credentials credentials = new KdbxCreds("123".getBytes()); 31 | super.database = JacksonDatabase.load(credentials, inputStream); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /simple/src/main/java/org/linguafranca/pwdb/kdbx/simple/converter/KeePassBooleanConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.simple.converter; 18 | 19 | import org.linguafranca.pwdb.kdbx.Helpers; 20 | import org.simpleframework.xml.convert.Converter; 21 | import org.simpleframework.xml.stream.InputNode; 22 | import org.simpleframework.xml.stream.OutputNode; 23 | 24 | /** 25 | * @author jo 26 | */ 27 | public class KeePassBooleanConverter implements Converter{ 28 | @Override 29 | public Boolean read(InputNode inputNode) throws Exception { 30 | return Helpers.toBoolean(inputNode.getValue()); 31 | } 32 | 33 | @Override 34 | public void write(OutputNode outputNode, Boolean bool) throws Exception { 35 | outputNode.setValue(Helpers.fromBoolean(bool)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/src/main/java/org/linguafranca/pwdb/Credentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb; 18 | 19 | import org.linguafranca.pwdb.security.Encryption; 20 | 21 | import java.security.MessageDigest; 22 | 23 | /** 24 | * Supports a contract that yields a key for decryption of databases 25 | * 26 | * @author jo 27 | */ 28 | public interface Credentials { 29 | 30 | /** 31 | * Implementation of no credentials 32 | */ 33 | class None implements Credentials { 34 | @Override 35 | public byte[] getKey() { 36 | MessageDigest md = Encryption.getSha256MessageDigestInstance(); 37 | return md.digest(new byte[0]); 38 | } 39 | } 40 | 41 | /** 42 | * Returns a digest of the composition of credentials supplied 43 | */ 44 | byte[] getKey(); 45 | } 46 | -------------------------------------------------------------------------------- /simple/src/test/java/org/linguafranca/pwdb/kdbx/simple/SimpleDatabaseLoaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.simple; 18 | 19 | import org.linguafranca.pwdb.checks.DatabaseLoaderChecks; 20 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 21 | import org.linguafranca.pwdb.Credentials; 22 | 23 | import java.io.InputStream; 24 | 25 | /** 26 | * @author jo 27 | */ 28 | public class SimpleDatabaseLoaderTest extends DatabaseLoaderChecks { 29 | 30 | public SimpleDatabaseLoaderTest() throws Exception { 31 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test123.kdbx"); 32 | // file has password credentials 33 | Credentials credentials = new KdbxCreds("123".getBytes()); 34 | super.database = SimpleDatabase.load(credentials, inputStream); 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /example/src/test/java/org/linguafranca/pwdb/kdbx/validation/Issue38Test.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.validation; 2 | 3 | import org.junit.Test; 4 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 5 | import org.linguafranca.pwdb.kdbx.dom.DomDatabaseWrapper; 6 | import org.linguafranca.pwdb.kdbx.dom.DomEntryWrapper; 7 | 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.PrintStream; 11 | import java.util.List; 12 | 13 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 14 | 15 | /** 16 | * Bug report on GitHub, the Keyfile is Version 2 (Hex) 17 | */ 18 | public class Issue38Test { 19 | 20 | static PrintStream printStream = getTestPrintStream(); 21 | @Test 22 | public void testV2Keyfile() throws IOException { 23 | InputStream databaseStream = Issue38Test.class.getClassLoader().getResourceAsStream("issue-38/Database/Database.kdbx"); 24 | InputStream keyStream = Issue38Test.class.getClassLoader().getResourceAsStream("issue-38/Database/Database.keyx"); 25 | assert keyStream != null; 26 | KdbxCreds creds = new KdbxCreds("MyPassword".getBytes(), keyStream); 27 | assert databaseStream != null; 28 | DomDatabaseWrapper database = DomDatabaseWrapper.load(creds, databaseStream); 29 | List entries = database.findEntries("Sample Entry"); 30 | DomEntryWrapper entry = entries.get(0); 31 | printStream.println(entry.getTitle()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/converter/StringToDateConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb.kdbx.jackson.converter; 17 | 18 | import java.util.Date; 19 | import java.util.Objects; 20 | 21 | import org.linguafranca.pwdb.kdbx.Helpers; 22 | 23 | import com.fasterxml.jackson.databind.util.StdConverter; 24 | 25 | public class StringToDateConverter extends StdConverter { 26 | 27 | @Override 28 | public Date convert(String value) { 29 | // TODO: It would really be better if we could inhibit deserialize date elements that are not present 30 | if (Objects.isNull(value) || value.isEmpty()) { 31 | return null; 32 | } 33 | if(value.equals("${creationDate}")) { 34 | return new Date(); 35 | } 36 | return Helpers.toDate(value); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /kdb/src/main/java/org/linguafranca/pwdb/kdb/KdbIcon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdb; 18 | 19 | import org.linguafranca.pwdb.Icon; 20 | 21 | /** 22 | * Contains the index of an icon 23 | * 24 | * @author jo 25 | */ 26 | public class KdbIcon implements Icon { 27 | int index = 0; 28 | 29 | KdbIcon(int index) { 30 | this.index = index; 31 | } 32 | 33 | @Override 34 | public int getIndex() { 35 | return index; 36 | } 37 | 38 | @Override 39 | public void setIndex(int index) { 40 | this.index = index; 41 | } 42 | 43 | @Override 44 | public boolean equals(Object o) { 45 | if (this == o) return true; 46 | if (o == null || !(o instanceof Icon)) return false; 47 | 48 | Icon icon = (Icon) o; 49 | 50 | return index == icon.getIndex(); 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /dom/src/test/java/org/linguafranca/pwdb/kdbx/dom/DomHelperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.dom; 18 | 19 | import org.junit.Test; 20 | import org.linguafranca.pwdb.kdbx.Helpers; 21 | 22 | import java.io.PrintStream; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 26 | 27 | /** 28 | * @author jo 29 | */ 30 | public class DomHelperTest { 31 | 32 | static PrintStream printStream = getTestPrintStream(); 33 | 34 | @Test 35 | public void testBase64RandomUuid() throws Exception { 36 | // just check that it can do something 37 | String uuid1 = DomHelper.base64RandomUuid(); 38 | printStream.println(Helpers.uuidFromBase64(uuid1)); 39 | String uuid2 = DomHelper.base64RandomUuid(); 40 | printStream.println(Helpers.uuidFromBase64(uuid2)); 41 | } 42 | } -------------------------------------------------------------------------------- /kdb/src/test/java/org/linguafranca/pwdb/kdb/KdbSerializerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdb; 18 | 19 | import org.junit.Test; 20 | import org.linguafranca.pwdb.Database; 21 | import org.linguafranca.pwdb.Visitor; 22 | 23 | import java.io.InputStream; 24 | import java.io.PrintStream; 25 | 26 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 27 | 28 | /** 29 | * @author jo 30 | */ 31 | public class KdbSerializerTest { 32 | 33 | static PrintStream printStream = getTestPrintStream(); 34 | 35 | 36 | @Test 37 | public void testCreateKdbDatabase() throws Exception { 38 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test123.kdb"); 39 | Database database = KdbDatabase.load(new KdbCredentials.Password("123".getBytes()), inputStream); 40 | database.visit(new Visitor.Print(printStream)); 41 | } 42 | } -------------------------------------------------------------------------------- /simple/src/main/java/org/linguafranca/pwdb/kdbx/simple/converter/EmptyStringConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.simple.converter; 18 | 19 | import org.simpleframework.xml.convert.Converter; 20 | import org.simpleframework.xml.stream.InputNode; 21 | import org.simpleframework.xml.stream.OutputNode; 22 | 23 | /** 24 | * @author jo 25 | */ 26 | public class EmptyStringConverter implements Converter { 27 | @Override 28 | public String read(InputNode inputNode) throws Exception { 29 | String value = inputNode.getValue(); 30 | return value == null ? "": value; 31 | } 32 | 33 | @Override 34 | public void write(OutputNode outputNode, String s) throws Exception { 35 | if(s==null || s.equals("")) { 36 | outputNode.setValue(null); 37 | } else { 38 | outputNode.setValue(s); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /kdb/src/test/java/org/linguafranca/pwdb/kdb/KdbDatabaseLoaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdb; 18 | 19 | import org.linguafranca.pwdb.Credentials; 20 | import org.linguafranca.pwdb.checks.DatabaseLoaderChecks; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | /** 26 | * @author jo 27 | */ 28 | public class KdbDatabaseLoaderTest extends DatabaseLoaderChecks { 29 | 30 | public KdbDatabaseLoaderTest() throws IOException { 31 | // get an input stream from KDB file 32 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test123.kdb"); 33 | // file has password credentials 34 | Credentials credentials = new KdbCredentials.Password("123".getBytes()); 35 | // open database. 36 | super.database = KdbDatabase.load(credentials, inputStream); 37 | super.skipDateCheck = true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /kdb/src/test/java/org/linguafranca/pwdb/kdb/KdbDatabaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdb; 18 | 19 | import org.junit.Test; 20 | import org.linguafranca.pwdb.checks.BasicDatabaseChecks; 21 | import org.linguafranca.pwdb.Database; 22 | 23 | import java.io.IOException; 24 | 25 | import static org.junit.Assert.assertFalse; 26 | 27 | /** 28 | * @author Jo 29 | */ 30 | public class KdbDatabaseTest extends BasicDatabaseChecks { 31 | @Override 32 | public Database createDatabase() throws IOException { 33 | return new KdbDatabase(); 34 | } 35 | 36 | public KdbDatabaseTest() throws IOException { 37 | super(); 38 | } 39 | 40 | @Test 41 | public void supportedFunctionalityTest(){ 42 | assertFalse(database.supportsBinaryProperties()); 43 | assertFalse(database.supportsNonStandardPropertyNames()); 44 | assertFalse(database.supportsRecycleBin()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /simple/src/main/java/org/linguafranca/pwdb/kdbx/simple/converter/TimeConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.simple.converter; 18 | 19 | import org.linguafranca.pwdb.kdbx.Helpers; 20 | import org.simpleframework.xml.convert.Converter; 21 | import org.simpleframework.xml.stream.InputNode; 22 | import org.simpleframework.xml.stream.OutputNode; 23 | 24 | import java.util.Date; 25 | 26 | /** 27 | * @author jo 28 | */ 29 | public class TimeConverter implements Converter{ 30 | @Override 31 | public Date read(InputNode inputNode) throws Exception { 32 | String value = inputNode.getValue(); 33 | if (value.equals("${creationDate}")) { 34 | return new Date(); 35 | } 36 | return Helpers.toDate(value); 37 | } 38 | 39 | @Override 40 | public void write(OutputNode outputNode, Date date) throws Exception { 41 | outputNode.setValue(Helpers.fromDate(date)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /simple/src/main/java/org/linguafranca/pwdb/kdbx/simple/converter/UuidConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.simple.converter; 18 | 19 | import org.linguafranca.pwdb.kdbx.Helpers; 20 | import org.simpleframework.xml.convert.Converter; 21 | import org.simpleframework.xml.stream.InputNode; 22 | import org.simpleframework.xml.stream.OutputNode; 23 | 24 | import java.util.UUID; 25 | 26 | /** 27 | * @author jo 28 | */ 29 | public class UuidConverter implements Converter { 30 | @Override 31 | public UUID read(InputNode inputNode) throws Exception { 32 | String value = inputNode.getValue(); 33 | if (value == null || value.equals("")) { 34 | return UUID.randomUUID(); 35 | } 36 | return Helpers.uuidFromBase64(value); 37 | } 38 | 39 | @Override 40 | public void write(OutputNode outputNode, UUID uuid) throws Exception { 41 | outputNode.setValue(Helpers.base64FromUuid(uuid)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/JacksonHistory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb.kdbx.jackson; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; 22 | import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; 23 | 24 | public class JacksonHistory { 25 | 26 | @JacksonXmlProperty(localName = "Entry") /* Workaround jackson */ 27 | @JacksonXmlElementWrapper(useWrapping = false) 28 | private List entry; 29 | 30 | public JacksonHistory() { 31 | entry = new ArrayList<>(); 32 | } 33 | 34 | /** 35 | * @return the entry 36 | */ 37 | public List getEntry() { 38 | return entry; 39 | } 40 | 41 | /** 42 | * @param entry the entry to set 43 | */ 44 | public void setEntry(List entry) { 45 | this.entry = entry; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /jaxb/src/test/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbLoaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jaxb; 18 | 19 | import org.linguafranca.pwdb.checks.DatabaseLoaderChecks; 20 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | /** 26 | * @author jo 27 | */ 28 | public class JaxbLoaderTest extends DatabaseLoaderChecks { 29 | 30 | public JaxbLoaderTest() throws IOException { 31 | // get an input stream from kdbx file 32 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test123.kdbx"); 33 | // file has password credentials 34 | KdbxCreds credentials = new KdbxCreds("123".getBytes()); 35 | // open database. DomDatabaseWrapper is so-called, since it wraps 36 | // a W3C DOM, populated from the KeePass XML, and presents it 37 | // through a org.linguafranca.keepass.Database interface. 38 | super.database = JaxbDatabase.load(credentials, inputStream); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /jaxb/src/main/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbIcon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jaxb; 18 | 19 | import org.linguafranca.pwdb.Icon; 20 | 21 | /** 22 | * @author jo 23 | */ 24 | @SuppressWarnings("WeakerAccess") 25 | public class JaxbIcon implements Icon{ 26 | private int index; 27 | 28 | public JaxbIcon(int iconID) { 29 | index = iconID; 30 | } 31 | 32 | public JaxbIcon() { 33 | index = 0; 34 | } 35 | 36 | @Override 37 | public int getIndex() { 38 | return index; 39 | } 40 | 41 | @Override 42 | public void setIndex(int index) { 43 | this.index = index; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object o) { 48 | if (this == o) return true; 49 | if (o == null || getClass() != o.getClass()) return false; 50 | 51 | JaxbIcon that = (JaxbIcon) o; 52 | 53 | return index == that.index; 54 | 55 | } 56 | 57 | @Override 58 | public int hashCode() { 59 | return index; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /simple/src/main/java/org/linguafranca/pwdb/kdbx/simple/SimpleIcon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.simple; 18 | 19 | import org.linguafranca.pwdb.Icon; 20 | 21 | /** 22 | * @author jo 23 | */ 24 | @SuppressWarnings("WeakerAccess") 25 | public class SimpleIcon implements Icon { 26 | private int index; 27 | 28 | public SimpleIcon() { 29 | } 30 | 31 | public SimpleIcon(int index) { 32 | this.index = index; 33 | } 34 | 35 | @Override 36 | public int getIndex() { 37 | return index; 38 | } 39 | 40 | @Override 41 | public void setIndex(int i) { 42 | index = i; 43 | } 44 | 45 | @Override 46 | public boolean equals(Object o) { 47 | if (this == o) return true; 48 | if (o == null || getClass() != o.getClass()) return false; 49 | 50 | SimpleIcon that = (SimpleIcon) o; 51 | 52 | return index == that.index; 53 | 54 | } 55 | 56 | @Override 57 | public int hashCode() { 58 | return index; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /dom/src/main/java/org/linguafranca/pwdb/kdbx/dom/DomIconWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.dom; 18 | 19 | import org.linguafranca.pwdb.Icon; 20 | import org.w3c.dom.Element; 21 | 22 | /** 23 | * Class wraps Icons from a {@link DomSerializableDatabase} as {@link Icon} 24 | * 25 | * @author jo 26 | */ 27 | public class DomIconWrapper implements Icon { 28 | 29 | private final Element element; 30 | 31 | public DomIconWrapper(Element element) { 32 | this.element = element; 33 | } 34 | 35 | @Override 36 | public int getIndex() { 37 | return Integer.parseInt(element.getTextContent()); 38 | } 39 | 40 | @Override 41 | public void setIndex(int index) { 42 | element.setTextContent(String.valueOf(index)); 43 | } 44 | 45 | @Override 46 | public boolean equals(Object o) { 47 | if (this == o) return true; 48 | if (o == null || !(o instanceof Icon)) return false; 49 | 50 | Icon that = (Icon) o; 51 | 52 | return this.getIndex() == that.getIndex(); 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /example/src/test/java/org/linguafranca/pwdb/kdbx/SaxParseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx; 18 | 19 | import org.junit.Test; 20 | import org.xml.sax.SAXException; 21 | 22 | import javax.xml.parsers.ParserConfigurationException; 23 | import java.io.IOException; 24 | import java.io.OutputStream; 25 | import java.io.PrintWriter; 26 | 27 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 28 | 29 | /** 30 | * @author jo 31 | */ 32 | 33 | public class SaxParseTest extends SaxParse { 34 | 35 | OutputStream outputStream = getTestPrintStream(); 36 | @Test 37 | public void exampleSaxParsingV3 () throws IOException, SAXException, ParserConfigurationException { 38 | super.exampleSaxParsing("test123.kdbx", new KdbxCreds("123".getBytes()), new PrintWriter(outputStream)); 39 | } 40 | @Test 41 | public void exampleSaxParsingV4 () throws IOException, SAXException, ParserConfigurationException { 42 | super.exampleSaxParsing("V4-AES-AES.kdbx", new KdbxCreds("123".getBytes()), new PrintWriter(outputStream)); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/JacksonIcon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jackson; 18 | 19 | import org.linguafranca.pwdb.Icon; 20 | 21 | /** 22 | * @author giusvale 23 | */ 24 | public class JacksonIcon implements Icon { 25 | 26 | private int index; 27 | 28 | public JacksonIcon(int iconID) { 29 | index = iconID; 30 | } 31 | 32 | public JacksonIcon() { 33 | this.index = 0; 34 | } 35 | 36 | @Override 37 | public int getIndex() { 38 | return this.index; 39 | } 40 | 41 | @Override 42 | public void setIndex(int index) { 43 | this.index = index; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object o) { 48 | if (this == o) 49 | return true; 50 | if (o == null || getClass() != o.getClass()) 51 | return false; 52 | 53 | JacksonIcon that = (JacksonIcon) o; 54 | 55 | return index == that.index; 56 | 57 | } 58 | 59 | @Override 60 | public int hashCode() { 61 | return index; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /simple/src/main/java/org/linguafranca/pwdb/kdbx/simple/converter/Base64ByteArrayConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.simple.converter; 18 | 19 | import org.linguafranca.pwdb.kdbx.Helpers; 20 | import org.linguafranca.pwdb.kdbx.simple.model.KeePassFile; 21 | import org.simpleframework.xml.convert.Converter; 22 | import org.simpleframework.xml.stream.InputNode; 23 | import org.simpleframework.xml.stream.OutputNode; 24 | 25 | /** 26 | * @author jo 27 | */ 28 | public class Base64ByteArrayConverter implements Converter{ 29 | @Override 30 | public KeePassFile.ByteArray read(InputNode inputNode) throws Exception { 31 | String input = inputNode.getValue(); 32 | byte[] value = input == null? new byte[0] : input.getBytes(); 33 | return new KeePassFile.ByteArray(Helpers.decodeBase64Content(value, false)); 34 | } 35 | 36 | @Override 37 | public void write(OutputNode outputNode, KeePassFile.ByteArray bytes) throws Exception { 38 | outputNode.setValue(Helpers.encodeBase64Content(bytes.getContent(), false)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /dom/src/test/java/org/linguafranca/pwdb/kdbx/dom/DomDatabaseWrapperLoaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.dom; 18 | 19 | import org.linguafranca.pwdb.checks.DatabaseLoaderChecks; 20 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 21 | import org.linguafranca.pwdb.Credentials; 22 | 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | 26 | /** 27 | * @author jo 28 | */ 29 | public class DomDatabaseWrapperLoaderTest extends DatabaseLoaderChecks { 30 | 31 | public DomDatabaseWrapperLoaderTest() throws IOException { 32 | // get an input stream from kdbx file 33 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test123.kdbx"); 34 | // file has password credentials 35 | Credentials credentials = new KdbxCreds("123".getBytes()); 36 | // open database. DomDatabaseWrapper is so-called, since it wraps 37 | // a W3C DOM, populated from the KeePass XML, and presents it 38 | // through a org.linguafranca.keepass.Database interface. 39 | super.database = DomDatabaseWrapper.load(credentials, inputStream); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /example/src/test/java/org/linguafranca/pwdb/kdbx/UtilTest.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.io.PrintWriter; 8 | 9 | import static org.linguafranca.pwdb.kdbx.Util.*; 10 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 11 | 12 | public class UtilTest { 13 | 14 | OutputStream outputStream = getTestPrintStream(); 15 | @Test public void listDatabaseTest() throws IOException { 16 | listDatabase("V3-CustomIcon.kdbx", new KdbxCreds("123".getBytes()), outputStream); 17 | } 18 | 19 | @Test 20 | public void listXmlTest() throws IOException { 21 | PrintWriter writer = new PrintWriter(outputStream); 22 | listXml("V3-CustomIcon.kdbx", new KdbxCreds("123".getBytes()), writer); 23 | writer.flush(); 24 | } 25 | 26 | /** 27 | * List Database Encryption Characteristics 28 | */ 29 | @Test 30 | public void listKdbxHeaderParams () throws IOException { 31 | PrintWriter writer = new PrintWriter(outputStream); 32 | listKdbxHeaderProperties("test123.kdbx", writer); 33 | listKdbxHeaderProperties("V4-AES-AES.kdbx", writer); 34 | listKdbxHeaderProperties("V4-AES-Argon2.kdbx", writer); 35 | listKdbxHeaderProperties("V4-ChaCha20-AES.kdbx", writer); 36 | listKdbxHeaderProperties("V4-ChaCha20-Argon2-Attachment.kdbx", writer); 37 | writer.flush(); 38 | } 39 | 40 | @Test 41 | public void listHeaderPropertiesAndXml() throws IOException { 42 | PrintWriter writer = new PrintWriter(outputStream); 43 | listKdbxHeaderProperties("V4-AES-Argon2-CustomIcon.kdbx", writer); 44 | listXml("V4-AES-Argon2-CustomIcon.kdbx", new KdbxCreds("123".getBytes()), writer); 45 | writer.flush(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | KeePassJava2-parent 5 | org.linguafranca.pwdb 6 | 2.2.4 7 | 8 | 4.0.0 9 | 10 | test 11 | PWDB :: Test 12 | Contains the shared test classes for exercising the functionality of a PWDB database implementation. 13 | 14 | 15 | true 16 | 17 | 18 | 19 | 20 | org.linguafranca.pwdb 21 | database 22 | ${project.version} 23 | 24 | 25 | org.linguafranca.pwdb 26 | util 27 | 2.2.4 28 | test 29 | 30 | 31 | 32 | 33 | 34 | 35 | org.apache.maven.plugins 36 | maven-jar-plugin 37 | 2.2 38 | 39 | 40 | 41 | test-jar 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /jaxb/src/test/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbSerializableDatabaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jaxb; 18 | 19 | import org.junit.Test; 20 | import org.linguafranca.pwdb.StreamFormat; 21 | import org.linguafranca.pwdb.Visitor; 22 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 23 | 24 | import java.io.InputStream; 25 | import java.io.PrintStream; 26 | 27 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 28 | 29 | /** 30 | * @author jo 31 | */ 32 | public class JaxbSerializableDatabaseTest { 33 | 34 | static PrintStream printStream = getTestPrintStream(); 35 | 36 | @Test 37 | public void createEmptyDatabase() throws Exception { 38 | JaxbDatabase db = JaxbDatabase.createEmptyDatabase(); 39 | db.save(new StreamFormat.None(), new KdbxCreds.None(), printStream); 40 | } 41 | @Test 42 | public void loadXml() throws Exception { 43 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test123.kdbx"); 44 | JaxbDatabase database = JaxbDatabase.load(new KdbxCreds("123".getBytes()), inputStream); 45 | database.visit(new Visitor.Print(printStream)); 46 | database.save(new StreamFormat.None(), new KdbxCreds.None(), printStream); 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /example/src/test/java/org/linguafranca/pwdb/kdbx/validation/Issue70Test.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.validation; 2 | 3 | import org.junit.Test; 4 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 5 | import org.linguafranca.pwdb.kdbx.jackson.JacksonDatabase; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | /** 11 | * Review Issue-70 https://github.com/jorabin/KeePassJava2/issues/70 12 | */ 13 | public class Issue70Test { 14 | 15 | public static final String TEST_RESOURCE1 = "issue-70/test2.kdbx"; 16 | public static final KdbxCreds CREDENTIALS1 = new KdbxCreds("KeePassJava2".getBytes()); 17 | public static final String TEST_RESOURCE2 = "Database-4.1-123.kdbx"; 18 | public static final KdbxCreds CREDENTIALS2 = new KdbxCreds("123".getBytes()); 19 | public static final String TEST_RESOURCE3 = "issue-70/test-hugoo10.kdbx"; 20 | public static final KdbxCreds CREDENTIALS3 = new KdbxCreds("test".getBytes()); 21 | 22 | 23 | /* custom data missing from meta */ 24 | @Test 25 | public void testCustomData() throws IOException { 26 | try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(TEST_RESOURCE1)) { 27 | JacksonDatabase database = JacksonDatabase.load(CREDENTIALS1, inputStream); 28 | } 29 | } 30 | 31 | @Test 32 | public void testFileFormat_4_1() throws IOException { 33 | try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(TEST_RESOURCE2)){ 34 | JacksonDatabase database = JacksonDatabase.load(CREDENTIALS2, inputStream); 35 | } 36 | } 37 | 38 | /* custom data missing from entry definition */ 39 | @Test 40 | public void testCustomData2() throws IOException { 41 | try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(TEST_RESOURCE3)){ 42 | JacksonDatabase database = JacksonDatabase.load(CREDENTIALS3, inputStream); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /jaxb/src/test/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbPropertyValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb.kdbx.jaxb; 17 | 18 | import org.linguafranca.pwdb.Credentials; 19 | import org.linguafranca.pwdb.Database; 20 | import org.linguafranca.pwdb.checks.PropertyValueChecks; 21 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 22 | 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.io.OutputStream; 26 | 27 | public class JaxbPropertyValueTest extends PropertyValueChecks { 28 | 29 | public JaxbPropertyValueTest() throws IOException { 30 | super(false); 31 | } 32 | 33 | 34 | @Override 35 | public Database createDatabase() throws IOException { 36 | return new JaxbDatabase(); 37 | } 38 | 39 | @Override 40 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 41 | database.save(credentials, outputStream); 42 | } 43 | 44 | @Override 45 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 46 | try { 47 | return JaxbDatabase.load(credentials, inputStream); 48 | } catch (Exception e) { 49 | throw new IOException(e); 50 | } 51 | } 52 | 53 | @Override 54 | public Credentials getCreds(byte[] creds) { 55 | return new KdbxCreds(creds); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /dom/src/test/java/org/linguafranca/pwdb/kdbx/dom/DomPropertyValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb.kdbx.dom; 17 | 18 | import org.linguafranca.pwdb.Credentials; 19 | import org.linguafranca.pwdb.Database; 20 | import org.linguafranca.pwdb.checks.PropertyValueChecks; 21 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 22 | 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.io.OutputStream; 26 | 27 | public class DomPropertyValueTest extends PropertyValueChecks { 28 | 29 | public DomPropertyValueTest() throws IOException { 30 | super(false); 31 | } 32 | 33 | 34 | @Override 35 | public Database createDatabase() throws IOException { 36 | return new DomDatabaseWrapper(); 37 | } 38 | 39 | @Override 40 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 41 | database.save(credentials, outputStream); 42 | } 43 | 44 | @Override 45 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 46 | try { 47 | return DomDatabaseWrapper.load(credentials, inputStream); 48 | } catch (Exception e) { 49 | throw new IOException(e); 50 | } 51 | } 52 | 53 | @Override 54 | public Credentials getCreds(byte[] creds) { 55 | return new KdbxCreds(creds); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /simple/src/test/java/org/linguafranca/pwdb/kdbx/simple/SimplePropertyValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb.kdbx.simple; 17 | 18 | import org.linguafranca.pwdb.Credentials; 19 | import org.linguafranca.pwdb.Database; 20 | import org.linguafranca.pwdb.checks.PropertyValueChecks; 21 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 22 | 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.io.OutputStream; 26 | 27 | public class SimplePropertyValueTest extends PropertyValueChecks { 28 | 29 | public SimplePropertyValueTest() throws IOException { 30 | super(false); 31 | } 32 | 33 | 34 | @Override 35 | public Database createDatabase() throws IOException { 36 | return new SimpleDatabase(); 37 | } 38 | 39 | @Override 40 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 41 | database.save(credentials, outputStream); 42 | } 43 | 44 | @Override 45 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 46 | try { 47 | return SimpleDatabase.load(credentials, inputStream); 48 | } catch (Exception e) { 49 | throw new IOException(e); 50 | } 51 | } 52 | 53 | @Override 54 | public Credentials getCreds(byte[] creds) { 55 | return new KdbxCreds(creds); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /dom/src/test/java/org/linguafranca/pwdb/kdbx/dom/DomBinaryPropertyV3Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.dom; 18 | 19 | import org.linguafranca.pwdb.checks.BinaryPropertyChecks; 20 | import org.linguafranca.pwdb.Database; 21 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 22 | import org.linguafranca.pwdb.Credentials; 23 | 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.io.OutputStream; 27 | 28 | /** 29 | * @author jo 30 | */ 31 | public class DomBinaryPropertyV3Test extends BinaryPropertyChecks { 32 | 33 | public DomBinaryPropertyV3Test() throws IOException { 34 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("Attachment.kdbx"); 35 | database = DomDatabaseWrapper.load(new KdbxCreds("123".getBytes()), inputStream); 36 | } 37 | 38 | @Override 39 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 40 | database.save(credentials, outputStream); 41 | } 42 | 43 | @Override 44 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 45 | return DomDatabaseWrapper.load(credentials, inputStream); 46 | } 47 | 48 | @Override 49 | public Database newDatabase() { 50 | return new DomDatabaseWrapper(); 51 | } 52 | 53 | @Override 54 | public Credentials getCreds(byte[] creds) { 55 | return new KdbxCreds(creds); 56 | } 57 | } -------------------------------------------------------------------------------- /jaxb/src/test/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbBinaryPropertyV3Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jaxb; 18 | 19 | import org.linguafranca.pwdb.Database; 20 | import org.linguafranca.pwdb.checks.BinaryPropertyChecks; 21 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 22 | import org.linguafranca.pwdb.Credentials; 23 | 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.io.OutputStream; 27 | 28 | /** 29 | * @author jo 30 | */ 31 | public class JaxbBinaryPropertyV3Test extends BinaryPropertyChecks { 32 | 33 | public JaxbBinaryPropertyV3Test() throws IOException { 34 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("Attachment.kdbx"); 35 | database = JaxbDatabase.load(new KdbxCreds("123".getBytes()),inputStream); 36 | } 37 | 38 | @Override 39 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 40 | database.save(credentials,outputStream); 41 | } 42 | 43 | 44 | @Override 45 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 46 | return JaxbDatabase.load(credentials, inputStream); 47 | } 48 | 49 | @Override 50 | public Database newDatabase() { 51 | return new JaxbDatabase(); 52 | } 53 | @Override 54 | public Credentials getCreds(byte[] creds) { 55 | return new KdbxCreds(creds); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /jaxb/src/generated/java/org/linguafranca/pwdb/kdbx/jaxb/binding/History.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 3 | // See http://java.sun.com/xml/jaxb 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2023.05.17 at 11:23:19 AM BST 6 | // 7 | 8 | 9 | package org.linguafranca.pwdb.kdbx.jaxb.binding; 10 | 11 | import javax.xml.bind.annotation.XmlAccessType; 12 | import javax.xml.bind.annotation.XmlAccessorType; 13 | import javax.xml.bind.annotation.XmlElement; 14 | import javax.xml.bind.annotation.XmlRootElement; 15 | import javax.xml.bind.annotation.XmlType; 16 | 17 | 18 | /** 19 | *

Java class for anonymous complex type. 20 | * 21 | *

The following schema fragment specifies the expected content contained within this class. 22 | * 23 | *

24 |  * <complexType>
25 |  *   <complexContent>
26 |  *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
27 |  *       <sequence>
28 |  *         <element ref="{}Entry"/>
29 |  *       </sequence>
30 |  *     </restriction>
31 |  *   </complexContent>
32 |  * </complexType>
33 |  * 
34 | * 35 | * 36 | */ 37 | @XmlAccessorType(XmlAccessType.FIELD) 38 | @XmlType(name = "", propOrder = { 39 | "entry" 40 | }) 41 | @XmlRootElement(name = "History") 42 | public class History { 43 | 44 | @XmlElement(name = "Entry", required = true) 45 | protected JaxbEntryBinding entry; 46 | 47 | /** 48 | * Gets the value of the entry property. 49 | * 50 | * @return 51 | * possible object is 52 | * {@link JaxbEntryBinding } 53 | * 54 | */ 55 | public JaxbEntryBinding getEntry() { 56 | return entry; 57 | } 58 | 59 | /** 60 | * Sets the value of the entry property. 61 | * 62 | * @param value 63 | * allowed object is 64 | * {@link JaxbEntryBinding } 65 | * 66 | */ 67 | public void setEntry(JaxbEntryBinding value) { 68 | this.entry = value; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /database/src/main/java/org/linguafranca/pwdb/security/ChaCha.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.security; 2 | 3 | import org.bouncycastle.crypto.StreamCipher; 4 | import org.bouncycastle.crypto.engines.ChaCha7539Engine; 5 | import org.bouncycastle.crypto.io.CipherInputStream; 6 | import org.bouncycastle.crypto.io.CipherOutputStream; 7 | import org.bouncycastle.crypto.params.KeyParameter; 8 | import org.bouncycastle.crypto.params.ParametersWithIV; 9 | 10 | import java.io.InputStream; 11 | import java.io.OutputStream; 12 | import java.util.UUID; 13 | 14 | /** 15 | * ChaCha20 may be used for the inner stream as well as for the underlying database encryption scheme 16 | *

17 | * A singleton 18 | */ 19 | public class ChaCha implements CipherAlgorithm { 20 | 21 | private static final UUID CHA_CHA_20_CIPHER = UUID.fromString("d6038a2b-8b6f-4cb5-a524-339a31dbb59a"); 22 | 23 | private static final String name = "CHA_CHA_20"; 24 | 25 | // hide constructor to enforce singleton 26 | private ChaCha(){} 27 | private static final ChaCha instance = new ChaCha(); 28 | 29 | public static ChaCha getInstance() { 30 | return instance; 31 | } 32 | 33 | @Override 34 | public UUID getCipherUuid() { 35 | return CHA_CHA_20_CIPHER; 36 | } 37 | 38 | @Override 39 | public String getName(){ 40 | return name; 41 | } 42 | 43 | @Override 44 | public InputStream getDecryptedInputStream(InputStream encryptedInputStream, byte[] key, byte[] iv) { 45 | final ParametersWithIV keyAndIV = new ParametersWithIV(new KeyParameter(key), iv); 46 | StreamCipher cipher = new ChaCha7539Engine(); 47 | cipher.init(false, keyAndIV); 48 | return new CipherInputStream(encryptedInputStream, cipher); 49 | } 50 | 51 | @Override 52 | public OutputStream getEncryptedOutputStream(OutputStream decryptedOutputStream, byte[] key, byte[] iv) { 53 | final ParametersWithIV keyAndIV = new ParametersWithIV(new KeyParameter(key), iv); 54 | StreamCipher cipher = new ChaCha7539Engine(); 55 | cipher.init(true, keyAndIV); 56 | return new CipherOutputStream(decryptedOutputStream, cipher); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | KeePassJava2-parent 21 | org.linguafranca.pwdb 22 | 2.2.4 23 | ../pom.xml 24 | 25 | 4.0.0 26 | 27 | example 28 | PWDB :: Example 29 | Examples of how to use PWDB 30 | 31 | 32 | true 33 | 34 | 35 | 36 | 37 | org.linguafranca.pwdb 38 | KeePassJava2 39 | ${project.version} 40 | 41 | 42 | io.github.novacrypto 43 | SecureString 44 | 2022.01.17 45 | 46 | 47 | org.linguafranca.pwdb 48 | test 49 | ${project.version} 50 | test-jar 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /kdbx/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | KeePassJava2-parent 21 | org.linguafranca.pwdb 22 | 2.2.4 23 | ../pom.xml 24 | 25 | 4.0.0 26 | 27 | KeePassJava2-kdbx 28 | KeePassJava2 :: KDBX 29 | Base classes and resources for other KDBX modules. 30 | KDBX Stream Support. 31 | Security support. 32 | 33 | 34 | 35 | 36 | 37 | org.linguafranca.pwdb 38 | database 39 | ${project.version} 40 | 41 | 42 | commons-codec 43 | commons-codec 44 | 1.17.0 45 | 46 | 47 | org.linguafranca.pwdb 48 | test 49 | ${project.version} 50 | test-jar 51 | test 52 | 53 | 54 | -------------------------------------------------------------------------------- /kdbx/src/test/java/org/linguafranca/pwdb/kdbx/HelperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx; 18 | 19 | import org.junit.Test; 20 | 21 | import java.io.PrintStream; 22 | import java.util.UUID; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 26 | 27 | /** 28 | * tests the operation of Hex conversion 29 | */ 30 | public class HelperTest { 31 | static PrintStream printStream = getTestPrintStream(); 32 | 33 | @Test 34 | public void testBase64() throws Exception { 35 | String inputString = "0tU8XFRUX2TCk5tmmrshuQ=="; 36 | printStream.println("Input string: " + inputString); 37 | String hexString = "D2D53C5C54545F64C2939B669ABB21B9"; 38 | String convertedString = Helpers.hexStringFromBase64("0tU8XFRUX2TCk5tmmrshuQ=="); 39 | printStream.println("Converted string: " + convertedString); 40 | assertEquals(hexString, convertedString.toUpperCase()); 41 | 42 | UUID uuid = Helpers.uuidFromBase64(inputString); 43 | printStream.println("UUID: " + uuid.toString()); 44 | assertEquals("d2d53c5c-5454-5f64-c293-9b669abb21b9", uuid.toString()); 45 | 46 | String uuidHex = Helpers.hexStringFromUuid(uuid); 47 | printStream.println("Hex from UUID: " + uuidHex); 48 | assertEquals(hexString, uuidHex.toUpperCase()); 49 | 50 | String base64 = Helpers.base64FromUuid(uuid); 51 | printStream.println("Base 64: " + base64); 52 | assertEquals(inputString, base64); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /jackson/src/test/java/org/linguafranca/pwdb/JacksonPropertyValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb; 17 | 18 | import org.linguafranca.pwdb.checks.BasicDatabaseChecks; 19 | import org.linguafranca.pwdb.checks.PropertyValueChecks; 20 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 21 | import org.linguafranca.pwdb.kdbx.jackson.JacksonDatabase; 22 | import org.linguafranca.pwdb.kdbx.jackson.JacksonEntry; 23 | import org.linguafranca.pwdb.kdbx.jackson.JacksonGroup; 24 | import org.linguafranca.pwdb.kdbx.jackson.JacksonIcon; 25 | 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.io.OutputStream; 29 | 30 | public class JacksonPropertyValueTest extends PropertyValueChecks { 31 | 32 | public JacksonPropertyValueTest() throws IOException { 33 | super(true); 34 | } 35 | 36 | @Override 37 | public void saveDatabase(JacksonDatabase database, Credentials credentials, OutputStream outputStream) throws IOException { 38 | database.save(credentials, outputStream); 39 | } 40 | 41 | @Override 42 | public JacksonDatabase loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 43 | return JacksonDatabase.load(credentials, inputStream); 44 | } 45 | 46 | @Override 47 | public Credentials getCreds(byte[] creds) { 48 | return new KdbxCreds(creds); 49 | } 50 | @Override 51 | public JacksonDatabase createDatabase() throws IOException { 52 | return new JacksonDatabase(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /jackson/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | KeePassJava2-parent 20 | org.linguafranca.pwdb 21 | 2.2.4 22 | ../pom.xml 23 | 24 | 4.0.0 25 | 26 | KeePassJava2-jackson 27 | KeePassJava2 :: Jackson 28 | Contains a Jackson XML implementation for KDBX. 29 | 30 | 31 | 32 | org.linguafranca.pwdb 33 | KeePassJava2-kdbx 34 | ${project.version} 35 | 36 | 37 | org.linguafranca.pwdb 38 | test 39 | ${project.version} 40 | test-jar 41 | test 42 | 43 | 44 | com.fasterxml.jackson.dataformat 45 | jackson-dataformat-xml 46 | 2.18.2 47 | 48 | 49 | com.fasterxml.woodstox 50 | woodstox-core 51 | 7.0.0 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /kdbx/src/test/java/org/linguafranca/pwdb/security/StreamEncryptionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.security; 18 | 19 | import org.junit.Test; 20 | import org.linguafranca.pwdb.security.StreamEncryptor.*; 21 | 22 | import java.io.PrintStream; 23 | import java.security.SecureRandom; 24 | 25 | import static org.junit.Assert.assertEquals; 26 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 27 | 28 | /** 29 | * Verify that the inner random encryption works two-way 30 | * @author jo 31 | */ 32 | public class StreamEncryptionTest { 33 | 34 | static PrintStream printStream = getTestPrintStream(); 35 | 36 | @Test 37 | public void salsa20() { 38 | byte[] key = SecureRandom.getSeed(32); 39 | StreamEncryptor ss = new Salsa20(key); 40 | StreamEncryptor tt = new Salsa20(key); 41 | 42 | verifyTwoWay(ss, tt); 43 | } 44 | 45 | @Test 46 | public void chacha20() { 47 | byte[] key = SecureRandom.getSeed(32); 48 | StreamEncryptor ss = new ChaCha20(key); 49 | StreamEncryptor tt = new ChaCha20(key); 50 | 51 | verifyTwoWay(ss, tt); 52 | } 53 | 54 | private void verifyTwoWay(StreamEncryptor ss, StreamEncryptor tt) { 55 | 56 | byte[] e = ss.encrypt("new secret".getBytes()); 57 | byte[] f = ss.encrypt("secret 2".getBytes()); 58 | 59 | 60 | String s1 = new String(tt.encrypt(e)); 61 | String t1 = new String(tt.encrypt(f)); 62 | 63 | assertEquals("new secret", s1); 64 | assertEquals("secret 2", t1); 65 | 66 | printStream.println(s1); 67 | printStream.println(t1); 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /simple/src/test/java/org/linguafranca/pwdb/kdbx/simple/SimpleBinaryPropertyV4Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.simple; 18 | 19 | import org.junit.Ignore; 20 | import org.linguafranca.pwdb.Credentials; 21 | import org.linguafranca.pwdb.Database; 22 | import org.linguafranca.pwdb.checks.BinaryPropertyChecks; 23 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 24 | 25 | import java.io.IOException; 26 | import java.io.InputStream; 27 | import java.io.OutputStream; 28 | 29 | /** 30 | * @author jo 31 | */ 32 | @Ignore 33 | public class SimpleBinaryPropertyV4Test extends BinaryPropertyChecks { 34 | 35 | public SimpleBinaryPropertyV4Test() throws Exception { 36 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("V4-ChaCha20-Argon2-Attachment.kdbx"); 37 | database = SimpleDatabase.load(new KdbxCreds("123".getBytes()), inputStream); 38 | } 39 | 40 | @Override 41 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 42 | database.save(credentials, outputStream); 43 | } 44 | 45 | @Override 46 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 47 | try { 48 | return SimpleDatabase.load(credentials, inputStream); 49 | } catch (Exception e) { 50 | throw new RuntimeException(e); 51 | } 52 | } 53 | 54 | @Override 55 | public Database newDatabase() { 56 | return new SimpleDatabase(); 57 | } 58 | 59 | @Override 60 | public Credentials getCreds(byte[] creds) { 61 | return new KdbxCreds(creds); 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /jaxb/src/generated/java/org/linguafranca/pwdb/kdbx/jaxb/binding/ValueExtender.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 3 | // See http://java.sun.com/xml/jaxb 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2023.05.17 at 11:23:19 AM BST 6 | // 7 | 8 | 9 | package org.linguafranca.pwdb.kdbx.jaxb.binding; 10 | 11 | import javax.xml.bind.annotation.XmlAccessType; 12 | import javax.xml.bind.annotation.XmlAccessorType; 13 | import javax.xml.bind.annotation.XmlSeeAlso; 14 | import javax.xml.bind.annotation.XmlType; 15 | import javax.xml.bind.annotation.XmlValue; 16 | 17 | 18 | /** 19 | * Abstract parent for StringField/Value so that 20 | * to allow creation of a custom mapping that contains extra 21 | * non-serialised (transient) fields. 22 | * 23 | * 24 | *

Java class for ValueExtender complex type. 25 | * 26 | *

The following schema fragment specifies the expected content contained within this class. 27 | * 28 | *

29 |  * <complexType name="ValueExtender">
30 |  *   <simpleContent>
31 |  *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
32 |  *     </extension>
33 |  *   </simpleContent>
34 |  * </complexType>
35 |  * 
36 | * 37 | * 38 | */ 39 | @XmlAccessorType(XmlAccessType.FIELD) 40 | @XmlType(name = "ValueExtender", propOrder = { 41 | "value" 42 | }) 43 | @XmlSeeAlso({ 44 | org.linguafranca.pwdb.kdbx.jaxb.binding.StringField.Value.class 45 | }) 46 | public abstract class ValueExtender { 47 | 48 | @XmlValue 49 | protected String value; 50 | 51 | /** 52 | * Gets the value of the value property. 53 | * 54 | * @return 55 | * possible object is 56 | * {@link String } 57 | * 58 | */ 59 | public String getValue() { 60 | return value; 61 | } 62 | 63 | /** 64 | * Sets the value of the value property. 65 | * 66 | * @param value 67 | * allowed object is 68 | * {@link String } 69 | * 70 | */ 71 | public void setValue(String value) { 72 | this.value = value; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /database/src/main/java/org/linguafranca/pwdb/protect/ProtectedDatabase.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.protect; 2 | 3 | import org.linguafranca.pwdb.*; 4 | import org.linguafranca.pwdb.base.AbstractDatabase; 5 | 6 | import java.util.Collections; 7 | import java.util.List; 8 | 9 | /** 10 | * Base class for Databases which support storage using {@link PropertyValue}s. 11 | *

12 | * By default {@link Entry#STANDARD_PROPERTY_NAME_PASSWORD} is defined as protected and the property value strategy 13 | * establishes {@link org.linguafranca.pwdb.PropertyValue.StringStore} storage for unprotected values and 14 | * {@link org.linguafranca.pwdb.PropertyValue.SealedStore} for protected values. 15 | */ 16 | public abstract class ProtectedDatabase, G extends Group, E extends Entry, I extends Icon> extends AbstractDatabase { 17 | private PropertyValue.Strategy valueStrategy = new PropertyValue.Strategy.Default(); 18 | 19 | @Override 20 | public boolean shouldProtect(String propertyName){ 21 | return valueStrategy.getProtectedProperties().contains(propertyName); 22 | } 23 | 24 | @Override 25 | public void setShouldProtect(String propertyName, boolean protect){ 26 | if (protect) { 27 | valueStrategy.getProtectedProperties().add(propertyName); 28 | } else { 29 | valueStrategy.getProtectedProperties().remove(propertyName); 30 | } 31 | } 32 | 33 | @Override 34 | public List listShouldProtect(){ 35 | return Collections.unmodifiableList(valueStrategy.getProtectedProperties()); 36 | } 37 | 38 | /** 39 | * Get the default means of storage of unprotected and protected property values 40 | */ 41 | @Override 42 | public PropertyValue.Strategy getPropertyValueStrategy(){ 43 | return this.valueStrategy; 44 | } 45 | /** 46 | * Set the default means of storage of unprotected and protected property values 47 | * @param strategy a property value strategy 48 | */ 49 | @Override 50 | public void setPropertyValueStrategy(PropertyValue.Strategy strategy){ 51 | this.valueStrategy = strategy; 52 | } 53 | 54 | @Override 55 | public boolean supportsPropertyValueStrategy(){ 56 | return true; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /kdbx/src/main/java/org/linguafranca/pwdb/hashedblock/CollectingOutputStream.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.hashedblock; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import java.io.*; 6 | 7 | /** 8 | * Class allows the forwarding (as a filter) and collection of written bytes as a buffer 9 | * - e.g. to provide for HMAC operations 10 | * 11 | * @author jo 12 | */ 13 | public class CollectingOutputStream extends FilterOutputStream { 14 | 15 | private final ByteArrayOutputStream collectedBytes = new ByteArrayOutputStream(); 16 | private boolean collecting = true; 17 | 18 | /** 19 | * Create a collecting stream which is set to collect from the get go 20 | * 21 | * @param out the output stream to forward/collect 22 | */ 23 | public CollectingOutputStream(OutputStream out) { 24 | this(out, true); 25 | } 26 | 27 | /** 28 | * Create a collecting stream 29 | * 30 | * @param out the output stream to forward/collect 31 | * @param collecting whether the initial state is collecting or not 32 | */ 33 | public CollectingOutputStream(OutputStream out, boolean collecting) { 34 | super(out); 35 | this.collecting = collecting; 36 | } 37 | 38 | @Override 39 | public void write(int toWrite) throws IOException { 40 | super.write(toWrite); 41 | if (collecting) { 42 | collectedBytes.write(toWrite); 43 | } 44 | } 45 | 46 | @Override 47 | public void write(byte @NotNull [] b) throws IOException { 48 | write(b, 0, b.length); 49 | } 50 | 51 | @Override 52 | public void write(byte @NotNull [] b, int off, int len) throws IOException { 53 | super.write(b, off, len); 54 | } 55 | 56 | /** 57 | * Get the collected bytes as a byte array 58 | */ 59 | public byte[] getCollectedBytes() { 60 | return collectedBytes.toByteArray(); 61 | } 62 | 63 | /** 64 | * True if we are currently collecting bytes 65 | */ 66 | public boolean isCollecting() { 67 | return collecting; 68 | } 69 | 70 | /** 71 | * Cganeg the state of collecting bytes 72 | * @param collecting true to collect 73 | */ 74 | public void setCollecting(boolean collecting) { 75 | this.collecting = collecting; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /database/src/main/java/org/linguafranca/pwdb/SerializableDatabase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb; 18 | 19 | import org.linguafranca.pwdb.security.StreamEncryptor; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.io.OutputStream; 24 | 25 | /** 26 | * This interface allows for serialization and deserialization of databases, which is 27 | * theoretically decoupled from the actual format they use for serialization. 28 | *

29 | * Databases instantiate themselves from a stream and serialize to a stream, 30 | * and need to be able to encrypt and decrypt data (e.g. Protected fields in KDBX format). 31 | *

32 | * KDBX V3 databases contain a header hash (i.e. a hash of the contents of 33 | * some portion of the {@link StreamFormat} they have been loaded from or saved to). 34 | * Which means that databases must support the setting of this value after the header 35 | * has been written on save, and reading the value after load to allow for integrity checking. 36 | *

37 | * KDBX V4 databases have their attachments in the header so databases need to support setting 38 | * and getting of attachments for serialization 39 | */ 40 | public interface SerializableDatabase { 41 | 42 | SerializableDatabase load(InputStream inputStream) throws IOException; 43 | 44 | void save(OutputStream outputStream) throws IOException; 45 | 46 | StreamEncryptor getEncryption(); 47 | 48 | void setEncryption(StreamEncryptor encryption); 49 | 50 | byte[] getHeaderHash(); 51 | 52 | void setHeaderHash(byte[] hash); 53 | 54 | void addBinary(int index, byte[] payload); 55 | 56 | byte[] getBinary(int index); 57 | 58 | int getBinaryCount(); 59 | } 60 | -------------------------------------------------------------------------------- /simple/src/test/java/org/linguafranca/pwdb/kdbx/simple/SimpleBinaryPropertyV3Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.simple; 18 | 19 | import org.linguafranca.pwdb.checks.BinaryPropertyChecks; 20 | import org.linguafranca.pwdb.Database; 21 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 22 | import org.linguafranca.pwdb.Credentials; 23 | 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.io.OutputStream; 27 | 28 | /** 29 | * @author jo 30 | */ 31 | public class SimpleBinaryPropertyV3Test extends BinaryPropertyChecks { 32 | 33 | public SimpleBinaryPropertyV3Test() { 34 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("Attachment.kdbx"); 35 | try { 36 | database = SimpleDatabase.load(new KdbxCreds("123".getBytes()),inputStream); 37 | } catch (Exception e) { 38 | throw new IllegalStateException(e); 39 | } 40 | } 41 | 42 | @Override 43 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 44 | database.save(credentials, outputStream); 45 | } 46 | 47 | 48 | @Override 49 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 50 | try { 51 | return SimpleDatabase.load(credentials, inputStream); 52 | } catch (Exception e) { 53 | throw new RuntimeException(e); 54 | } 55 | } 56 | 57 | 58 | @Override 59 | public Database newDatabase() { 60 | return new SimpleDatabase(); 61 | } 62 | 63 | @Override 64 | public Credentials getCreds(byte[] creds) { 65 | return new KdbxCreds(creds); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /jackson/src/test/java/org/linguafranca/pwdb/JacksonBinaryPropertyV3Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb; 18 | 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.io.OutputStream; 22 | 23 | import org.linguafranca.pwdb.checks.BinaryPropertyChecks; 24 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 25 | import org.linguafranca.pwdb.kdbx.jackson.JacksonDatabase; 26 | 27 | public class JacksonBinaryPropertyV3Test extends BinaryPropertyChecks { 28 | 29 | 30 | public JacksonBinaryPropertyV3Test() { 31 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("Attachment.kdbx"); 32 | try { 33 | database = JacksonDatabase.load(new KdbxCreds("123".getBytes()),inputStream); 34 | } catch (Exception e) { 35 | throw new IllegalStateException(e); 36 | } 37 | } 38 | 39 | @Override 40 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 41 | database.save(credentials, outputStream); 42 | } 43 | 44 | @Override 45 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 46 | return JacksonDatabase.load(credentials, inputStream); 47 | } 48 | 49 | @Override 50 | public Database newDatabase() { 51 | Database result = null; 52 | try { 53 | result = new JacksonDatabase(); 54 | } catch(Exception e) { 55 | throw new RuntimeException(e); 56 | } 57 | return result; 58 | 59 | } 60 | 61 | @Override 62 | public Credentials getCreds(byte[] creds) { 63 | return new KdbxCreds(creds); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /dom/src/test/java/org/linguafranca/pwdb/kdbx/dom/DomBinaryPropertyV4Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.dom; 18 | 19 | import org.linguafranca.pwdb.Credentials; 20 | import org.linguafranca.pwdb.Database; 21 | import org.linguafranca.pwdb.StreamFormat; 22 | import org.linguafranca.pwdb.checks.BinaryPropertyChecks; 23 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 24 | import org.linguafranca.pwdb.kdbx.KdbxHeader; 25 | import org.linguafranca.pwdb.kdbx.KdbxStreamFormat; 26 | 27 | import java.io.IOException; 28 | import java.io.InputStream; 29 | import java.io.OutputStream; 30 | 31 | /** 32 | * @author jo 33 | */ 34 | public class DomBinaryPropertyV4Test extends BinaryPropertyChecks { 35 | 36 | public DomBinaryPropertyV4Test() throws IOException { 37 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("V4-ChaCha20-Argon2-Attachment.kdbx"); 38 | database = DomDatabaseWrapper.load(new KdbxCreds("123".getBytes()), inputStream); 39 | } 40 | 41 | @Override 42 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 43 | StreamFormat sf = new KdbxStreamFormat(new KdbxHeader(4)); 44 | database.save(sf, credentials, outputStream); 45 | } 46 | 47 | 48 | @Override 49 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 50 | return DomDatabaseWrapper.load(credentials, inputStream); 51 | } 52 | 53 | @Override 54 | public Database newDatabase() { 55 | return new DomDatabaseWrapper(); 56 | } 57 | 58 | @Override 59 | public Credentials getCreds(byte[] creds) { 60 | return new KdbxCreds(creds); 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /jaxb/src/test/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jaxb; 18 | 19 | import org.junit.Test; 20 | import org.linguafranca.pwdb.kdbx.jaxb.binding.KeePassFile; 21 | import org.linguafranca.pwdb.kdbx.jaxb.binding.StringField; 22 | 23 | import javax.xml.bind.*; 24 | import java.io.PrintStream; 25 | 26 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 27 | 28 | /** 29 | * @author jo 30 | */ 31 | public class JaxbTest { 32 | static PrintStream printStream = getTestPrintStream(); 33 | 34 | @Test 35 | public void unmarshal() throws JAXBException { 36 | JAXBContext jc = JAXBContext.newInstance(KeePassFile.class); 37 | Unmarshaller u = jc.createUnmarshaller(); 38 | u.setEventHandler(new ValidationEventHandler() { 39 | @Override 40 | public boolean handleEvent(ValidationEvent event) { 41 | printStream.println(event.getLocator().getLineNumber() +": "+ event.getMessage()); 42 | return true; 43 | } 44 | }); 45 | u.setListener(new Unmarshaller.Listener() { 46 | @Override 47 | public void afterUnmarshal(Object target, Object parent) { 48 | if (target instanceof StringField.Value) { 49 | StringField.Value value = (StringField.Value) target; 50 | printStream.println(value.getValue()); 51 | } 52 | super.afterUnmarshal(target, parent); 53 | } 54 | }); 55 | KeePassFile kpf = (KeePassFile) u.unmarshal(getClass().getClassLoader().getResourceAsStream("ExampleDatabase.xml")); 56 | printStream.println(kpf.getMeta().getDatabaseDescription()); 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /jaxb/src/test/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbBinaryPropertyV4Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jaxb; 18 | 19 | import org.junit.Ignore; 20 | import org.linguafranca.pwdb.Credentials; 21 | import org.linguafranca.pwdb.Database; 22 | import org.linguafranca.pwdb.StreamFormat; 23 | import org.linguafranca.pwdb.checks.BinaryPropertyChecks; 24 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 25 | import org.linguafranca.pwdb.kdbx.KdbxHeader; 26 | import org.linguafranca.pwdb.kdbx.KdbxStreamFormat; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.io.OutputStream; 31 | 32 | /** 33 | * @author jo 34 | */ 35 | @Ignore 36 | public class JaxbBinaryPropertyV4Test extends BinaryPropertyChecks { 37 | 38 | public JaxbBinaryPropertyV4Test() throws IOException { 39 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("V4-ChaCha20-Argon2-Attachment.kdbx"); 40 | database = JaxbDatabase.load(new KdbxCreds("123".getBytes()), inputStream); 41 | } 42 | 43 | @Override 44 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 45 | StreamFormat sf = new KdbxStreamFormat(new KdbxHeader(4)); 46 | database.save(sf, credentials, outputStream); 47 | } 48 | 49 | @Override 50 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 51 | return JaxbDatabase.load(credentials, inputStream); 52 | } 53 | 54 | @Override 55 | public Database newDatabase() { 56 | return new JaxbDatabase(); 57 | } 58 | 59 | @Override 60 | public Credentials getCreds(byte[] creds) { 61 | return new KdbxCreds(creds); 62 | } 63 | } -------------------------------------------------------------------------------- /jackson/src/test/java/org/linguafranca/pwdb/JacksonBinaryPropertyV4Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb; 17 | 18 | import java.io.IOException; 19 | import java.io.InputStream; 20 | import java.io.OutputStream; 21 | 22 | import org.linguafranca.pwdb.checks.BinaryPropertyChecks; 23 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 24 | import org.linguafranca.pwdb.kdbx.jackson.JacksonDatabase; 25 | 26 | public class JacksonBinaryPropertyV4Test extends BinaryPropertyChecks{ 27 | 28 | 29 | public JacksonBinaryPropertyV4Test() throws Exception{ 30 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("V4-ChaCha20-Argon2-Attachment.kdbx"); 31 | database = JacksonDatabase.load(new KdbxCreds("123".getBytes()), inputStream); 32 | } 33 | 34 | 35 | @Override 36 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 37 | database.save(credentials, outputStream); 38 | } 39 | 40 | @Override 41 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 42 | try { 43 | return JacksonDatabase.load(credentials, inputStream); 44 | } catch (Exception e) { 45 | throw new RuntimeException(e); 46 | } 47 | } 48 | 49 | @Override 50 | public Database newDatabase() { 51 | Database result = null; 52 | try { 53 | result = new JacksonDatabase(); 54 | } catch (Exception e) { 55 | throw new RuntimeException(e); 56 | } 57 | return result; 58 | 59 | } 60 | 61 | @Override 62 | public Credentials getCreds(byte[] creds) { 63 | return new KdbxCreds(creds); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /kdbx/src/test/java/org/linguafranca/pwdb/kdbx/HelpersTest.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.PrintStream; 6 | import java.text.ParseException; 7 | import java.time.Instant; 8 | import java.time.ZoneId; 9 | import java.time.ZonedDateTime; 10 | import java.util.Date; 11 | 12 | import static org.junit.Assert.*; 13 | import static org.linguafranca.pwdb.kdbx.Helpers.dateTimeFormatter; 14 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 15 | 16 | public class HelpersTest { 17 | 18 | static PrintStream printStream = getTestPrintStream(); 19 | 20 | public String testDate = "2023-05-09T16:11:29Z"; 21 | public Date testDateAsDate = Date.from(ZonedDateTime.parse(testDate, dateTimeFormatter).toInstant()); 22 | public String v4Encoding = "sWfs2w4AAAA="; 23 | 24 | @Test 25 | public void toDate() throws ParseException { 26 | Date date = Helpers.toDate(v4Encoding); 27 | assertEquals(testDateAsDate.getTime(), date.getTime()); 28 | } 29 | 30 | @Test 31 | public void toDate2() throws ParseException { 32 | Date date = Helpers.toDate(testDate); 33 | assertEquals(testDateAsDate, date); 34 | } 35 | 36 | @Test 37 | public void toDate3() throws ParseException { 38 | ZonedDateTime zdt = ZonedDateTime.parse(testDate, dateTimeFormatter); 39 | printStream.println(zdt); 40 | Instant instant = zdt.toInstant(); 41 | printStream.println(instant); 42 | Date date = Date.from(instant); 43 | printStream.println(date.clone()); 44 | assertEquals(instant.toEpochMilli(), date.getTime()); 45 | assertEquals(instant.toEpochMilli(), testDateAsDate.getTime()); 46 | } 47 | 48 | @Test 49 | public void fromDate() throws ParseException { 50 | Helpers.isV4.set(false); 51 | assertEquals(testDate, Helpers.fromDate(testDateAsDate)); 52 | Helpers.isV4.set(true); 53 | assertEquals(v4Encoding, Helpers.fromDate(testDateAsDate)); 54 | } 55 | 56 | @Test 57 | public void fromDateV3() throws ParseException { 58 | assertEquals(testDate, Helpers.fromDateV3(testDateAsDate)); 59 | } 60 | 61 | @Test 62 | public void fromDateV4() throws ParseException { 63 | String base64 = Helpers.fromDateV4(testDateAsDate); 64 | printStream.println(Helpers.toDate(base64)); 65 | assertEquals(v4Encoding, base64); 66 | } 67 | } -------------------------------------------------------------------------------- /example/src/main/java/org/linguafranca/pwdb/example/SecureCharBufferPropertyValue.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.example; 2 | 3 | import io.github.novacrypto.SecureCharBuffer; 4 | import org.linguafranca.pwdb.PropertyValue; 5 | 6 | import java.nio.ByteBuffer; 7 | import java.nio.CharBuffer; 8 | import java.nio.charset.StandardCharsets; 9 | 10 | /** 11 | * SecureCharBufferPropertyValue uses {@link SecureCharBuffer} 12 | */ 13 | public class SecureCharBufferPropertyValue implements PropertyValue { 14 | private final SecureCharBuffer value; 15 | 16 | /** 17 | * Builder for {@link SecureCharBufferPropertyValue} 18 | */ 19 | static class Factory implements PropertyValue.Factory { 20 | 21 | @Override 22 | public PropertyValue of(CharSequence aString) { 23 | return new SecureCharBufferPropertyValue(aString); 24 | } 25 | 26 | @Override 27 | public PropertyValue of(char[] value) { 28 | return new SecureCharBufferPropertyValue(value); 29 | } 30 | 31 | @Override 32 | public PropertyValue of(byte[] value) { 33 | return new SecureCharBufferPropertyValue(value); 34 | } 35 | } 36 | 37 | public SecureCharBufferPropertyValue(CharSequence aString) { 38 | this.value = SecureCharBuffer.withCapacity(aString.length()); 39 | this.value.append(aString); 40 | } 41 | 42 | public SecureCharBufferPropertyValue(char [] value) { 43 | this.value = SecureCharBuffer.withCapacity(value.length); 44 | this.value.append(CharBuffer.wrap(value)); 45 | } 46 | 47 | public SecureCharBufferPropertyValue(byte [] value) { 48 | this.value = SecureCharBuffer.withCapacity(value.length); 49 | this.value.append(StandardCharsets.UTF_8.decode(ByteBuffer.wrap(value))); 50 | } 51 | @Override 52 | public String getValueAsString() { 53 | return this.value.toStringAble().toString(); 54 | } 55 | 56 | @Override 57 | public CharSequence getValue() { 58 | return this.value; 59 | } 60 | 61 | @Override 62 | public char [] getValueAsChars() { 63 | return CharBuffer.wrap(value).array(); 64 | } 65 | 66 | @Override 67 | public byte [] getValueAsBytes() { 68 | return StandardCharsets.UTF_8.encode(CharBuffer.wrap(value)).array(); 69 | } 70 | 71 | @Override 72 | public boolean isProtected() { 73 | return true; 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /jaxb/src/generated/java/META-INF/sun-jaxb.episode: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /util/src/main/java/org/linguafranca/test/maven/MavenRunListener.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.test.maven; 2 | 3 | import org.junit.runner.Description; 4 | import org.junit.runner.notification.Failure; 5 | import org.junit.runner.notification.RunListener; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.slf4j.Marker; 9 | import org.slf4j.MarkerFactory; 10 | 11 | /** 12 | * Helper class to identify the test being run by maven surefire in the log output. This 13 | * is particularly useful if there is a lot of "chatty" testing going on. 14 | *

15 | * See: Using Custom Listeners and Reporters 16 | */ 17 | @RunListener.ThreadSafe 18 | public class MavenRunListener extends RunListener { 19 | static Logger logger = LoggerFactory.getLogger("MavenRunListener"); 20 | static Marker marker = MarkerFactory.getMarker("Starting Test"); 21 | static Marker endMarker = MarkerFactory.getMarker("Finished Test"); 22 | static Marker failMarker = MarkerFactory.getMarker("Failed Test"); 23 | static Marker assumeFailMarker = MarkerFactory.getMarker("Assumption Failed"); 24 | static Marker ignoredMarker = MarkerFactory.getMarker("Ignored Test"); 25 | 26 | @Override 27 | public void testStarted(Description description) throws Exception { 28 | super.testStarted(description); 29 | logger.info(marker, "{}", description.getDisplayName()); 30 | } 31 | 32 | @Override 33 | public void testFailure(Failure failure) throws Exception { 34 | super.testFailure(failure); 35 | logger.error(failMarker, "{} {}", failure.getMessage(), failure.getDescription().getDisplayName()); 36 | } 37 | 38 | @Override 39 | public void testAssumptionFailure(Failure failure) { 40 | super.testAssumptionFailure(failure); 41 | logger.warn(assumeFailMarker, "{} {}", failure.getMessage(), failure.getDescription().getDisplayName()); 42 | } 43 | 44 | @Override 45 | public void testIgnored(Description description) throws Exception { 46 | super.testIgnored(description); 47 | logger.info(ignoredMarker, "{}", description.getDisplayName()); 48 | } 49 | 50 | @Override 51 | public void testFinished(Description description) throws Exception { 52 | super.testFinished(description); 53 | logger.info(endMarker, "Finished {}", description.getDisplayName()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /all/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | KeePassJava2-parent 21 | org.linguafranca.pwdb 22 | 2.2.4 23 | ../pom.xml 24 | 25 | 26 | 4.0.0 27 | 28 | KeePassJava2 29 | KeePassJava2 :: All 30 | Supports KDBX Password Database Versions 3.1, 4 and 4.1. 31 | 32 | 33 | 34 | org.linguafranca.pwdb 35 | KeePassJava2-kdb 36 | ${project.version} 37 | 38 | 39 | org.linguafranca.pwdb 40 | KeePassJava2-dom 41 | ${project.version} 42 | 43 | 44 | org.linguafranca.pwdb 45 | KeePassJava2-jaxb 46 | ${project.version} 47 | 48 | 49 | org.linguafranca.pwdb 50 | KeePassJava2-simple 51 | ${project.version} 52 | 53 | 54 | org.linguafranca.pwdb 55 | KeePassJava2-jackson 56 | ${project.version} 57 | 58 | 59 | -------------------------------------------------------------------------------- /simple/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | KeePassJava2-parent 21 | org.linguafranca.pwdb 22 | 2.2.4 23 | ../pom.xml 24 | 25 | 4.0.0 26 | 27 | KeePassJava2-simple 28 | KeePassJava2 :: Simple 29 | Contains a Simple XML framework implementation of KDBX. 30 | 31 | 32 | 33 | org.linguafranca.pwdb 34 | KeePassJava2-kdbx 35 | ${project.version} 36 | 37 | 38 | org.linguafranca.pwdb 39 | test 40 | ${project.version} 41 | test-jar 42 | test 43 | 44 | 45 | com.carrotsearch.thirdparty 46 | simple-xml-safe 47 | 2.7.1 48 | 49 | 50 | org.apache.httpcomponents 51 | httpcore 52 | 4.4.16 53 | 54 | 55 | com.fasterxml 56 | aalto-xml 57 | 1.3.3 58 | 59 | 60 | -------------------------------------------------------------------------------- /dom/src/test/java/org/linguafranca/pwdb/kdbx/dom/DomDatabaseWrapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.dom; 18 | 19 | import org.linguafranca.pwdb.checks.BasicDatabaseChecks; 20 | import org.junit.Test; 21 | import org.linguafranca.pwdb.Database; 22 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 23 | import org.linguafranca.pwdb.StreamFormat; 24 | import org.linguafranca.pwdb.Credentials; 25 | 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.io.PrintStream; 29 | 30 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 31 | 32 | /** 33 | * @author jo 34 | */ 35 | public class DomDatabaseWrapperTest extends BasicDatabaseChecks { 36 | 37 | static PrintStream printStream = getTestPrintStream(); 38 | 39 | public DomDatabaseWrapperTest() throws IOException { 40 | } 41 | 42 | @Test 43 | public void inspectPasswordDatabase() throws IOException { 44 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test123.kdbx"); 45 | DomDatabaseWrapper database = new DomDatabaseWrapper(new KdbxCreds("123".getBytes()), inputStream); 46 | 47 | database.save(new StreamFormat.None(), new Credentials.None(), printStream); 48 | } 49 | 50 | @Test 51 | public void inspectKeyfileDatabase() throws IOException { 52 | InputStream keyFileInputStream = getClass().getClassLoader().getResourceAsStream("KeyFileDatabase.key"); 53 | Credentials credentials = new KdbxCreds("123".getBytes(), keyFileInputStream); 54 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("KeyFileDatabase.kdbx"); 55 | DomDatabaseWrapper database = new DomDatabaseWrapper(credentials, inputStream); 56 | 57 | database.save(new StreamFormat.None(), new Credentials.None(), printStream); 58 | } 59 | 60 | @Override 61 | public Database createDatabase() throws IOException { 62 | return new DomDatabaseWrapper(); 63 | } 64 | } -------------------------------------------------------------------------------- /jaxb/src/generated/java/org/linguafranca/pwdb/kdbx/jaxb/binding/CustomData.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 3 | // See http://java.sun.com/xml/jaxb 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2023.05.17 at 11:23:19 AM BST 6 | // 7 | 8 | 9 | package org.linguafranca.pwdb.kdbx.jaxb.binding; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import javax.xml.bind.annotation.XmlAccessType; 14 | import javax.xml.bind.annotation.XmlAccessorType; 15 | import javax.xml.bind.annotation.XmlAnyElement; 16 | import javax.xml.bind.annotation.XmlType; 17 | 18 | 19 | /** 20 | * Third party programs and plugins can put custom data here. 21 | * Unique element names should be used, e.g. "PluginName_ItemName". 22 | * 23 | * 24 | *

Java class for customData complex type. 25 | * 26 | *

The following schema fragment specifies the expected content contained within this class. 27 | * 28 | *

29 |  * <complexType name="customData">
30 |  *   <complexContent>
31 |  *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
32 |  *       <sequence>
33 |  *         <any maxOccurs="unbounded" minOccurs="0"/>
34 |  *       </sequence>
35 |  *     </restriction>
36 |  *   </complexContent>
37 |  * </complexType>
38 |  * 
39 | * 40 | * 41 | */ 42 | @XmlAccessorType(XmlAccessType.FIELD) 43 | @XmlType(name = "customData", propOrder = { 44 | "any" 45 | }) 46 | public class CustomData { 47 | 48 | @XmlAnyElement(lax = true) 49 | protected List any; 50 | 51 | /** 52 | * Gets the value of the any property. 53 | * 54 | *

55 | * This accessor method returns a reference to the live list, 56 | * not a snapshot. Therefore any modification you make to the 57 | * returned list will be present inside the JAXB object. 58 | * This is why there is not a set method for the any property. 59 | * 60 | *

61 | * For example, to add a new item, do as follows: 62 | *

63 |      *    getAny().add(newItem);
64 |      * 
65 | * 66 | * 67 | *

68 | * Objects of the following type(s) are allowed in the list 69 | * {@link Object } 70 | * 71 | * 72 | */ 73 | public List getAny() { 74 | if (any == null) { 75 | any = new ArrayList(); 76 | } 77 | return this.any; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /kdbx/src/main/java/org/linguafranca/pwdb/hashedblock/CollectingInputStream.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.hashedblock; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.FilterInputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | /** 11 | * Class allows the forwarding (as a filter) and collection of read bytes as a buffer 12 | * - e.g. to provide for HMAC operations 13 | * 14 | * @author jo 15 | */ 16 | public class CollectingInputStream extends FilterInputStream { 17 | 18 | private ByteArrayOutputStream collectedBytes = new ByteArrayOutputStream(); 19 | private boolean collecting = true; 20 | 21 | /** 22 | * Create a collecting stream which is set to collect from the get go 23 | * 24 | * @param in the input stream to forward/collect 25 | */ 26 | public CollectingInputStream(InputStream in) { 27 | this(in, true); 28 | } 29 | 30 | /** 31 | * Create a collecting stream 32 | * 33 | * @param in the input stream to forward/collect 34 | * @param collecting whether the initial state is collecting or not 35 | */ 36 | public CollectingInputStream(InputStream in, boolean collecting) { 37 | super(in); 38 | this.collecting = collecting; 39 | } 40 | 41 | @Override 42 | public int read() throws IOException { 43 | int result = super.read(); 44 | if (collecting && result != -1) { 45 | collectedBytes.write(result); 46 | } 47 | return result; 48 | } 49 | 50 | @Override 51 | public int read(@NotNull byte[] b) throws IOException { 52 | return read(b, 0, b.length); 53 | } 54 | 55 | @Override 56 | public int read(@NotNull byte[] b, int off, int len) throws IOException { 57 | int result = super.read(b, off, len); 58 | if (collecting && result != -1) { 59 | collectedBytes.write(b, off, result); 60 | } 61 | return result; 62 | } 63 | 64 | @Override 65 | public long skip(long n) throws IOException { 66 | return super.skip(n); 67 | } 68 | 69 | /** 70 | * Get the collected bytes as a byte array 71 | */ 72 | public byte[] getCollectedBytes() { 73 | return collectedBytes.toByteArray(); 74 | } 75 | 76 | /** 77 | * True if we are currently collecting bytes 78 | */ 79 | public boolean isCollecting() { 80 | return collecting; 81 | } 82 | 83 | /** 84 | * Cganeg the state of collecting bytes 85 | * @param collecting true to collect 86 | */ 87 | public void setCollecting(boolean collecting) { 88 | this.collecting = collecting; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /kdbx/src/main/java/org/linguafranca/pwdb/kdbx/KdbxCreds.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx; 18 | 19 | import org.jetbrains.annotations.NotNull; 20 | import org.linguafranca.pwdb.Credentials; 21 | import org.linguafranca.pwdb.security.Encryption; 22 | 23 | import java.io.InputStream; 24 | import java.security.MessageDigest; 25 | 26 | /** 27 | * The class implements {@link Credentials} for KDBX files. 28 | * 29 | * @author jo 30 | */ 31 | public class KdbxCreds implements Credentials { 32 | 33 | private final byte[] key; 34 | 35 | /** 36 | * Constructor for password with KDBX Keyfile 37 | * @param password Master Password (new byte[0] if empty, not none) 38 | * @param inputStream inputstream of the keyfile 39 | */ 40 | public KdbxCreds(@NotNull byte[] password, @NotNull InputStream inputStream) { 41 | MessageDigest md = Encryption.getSha256MessageDigestInstance(); 42 | byte[] pwKey = md.digest(password); 43 | md.update(pwKey); 44 | 45 | byte[] keyFileData = KdbxKeyFile.load(inputStream); 46 | if (keyFileData == null) { 47 | throw new IllegalStateException("Could not read key file"); 48 | } 49 | this.key = md.digest(keyFileData); 50 | } 51 | 52 | /** 53 | * Constructor for KDBX Keyfile with no password 54 | * @param inputStream inputstream of the keyfile 55 | */ 56 | public KdbxCreds(@NotNull InputStream inputStream) { 57 | MessageDigest md = Encryption.getSha256MessageDigestInstance(); 58 | byte[] keyFileData = KdbxKeyFile.load(inputStream); 59 | if (keyFileData == null) { 60 | throw new IllegalStateException("Could not read key file"); 61 | } 62 | this.key = md.digest(keyFileData); 63 | } 64 | 65 | 66 | public KdbxCreds(@NotNull byte[] password) { 67 | MessageDigest md = Encryption.getSha256MessageDigestInstance(); 68 | byte[] digest = md.digest(password); 69 | key = md.digest(digest); 70 | } 71 | 72 | @Override 73 | public byte[] getKey() { 74 | return key; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/converter/ValueSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb.kdbx.jackson.converter; 17 | 18 | import com.fasterxml.jackson.core.JsonGenerator; 19 | import com.fasterxml.jackson.databind.SerializerProvider; 20 | import com.fasterxml.jackson.databind.ser.std.StdSerializer; 21 | import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; 22 | import org.apache.commons.codec.binary.Base64; 23 | import org.linguafranca.pwdb.PropertyValue; 24 | import org.linguafranca.pwdb.security.StreamEncryptor; 25 | 26 | import java.io.IOException; 27 | 28 | 29 | public class ValueSerializer extends StdSerializer { 30 | 31 | private final StreamEncryptor encryptor; 32 | private final PropertyValue.Strategy propertyValueStrategy; 33 | 34 | public ValueSerializer(StreamEncryptor encryptor, PropertyValue.Strategy propertyValueStrategy) { 35 | super(ValueSerializer.class, false); 36 | this.encryptor = encryptor; 37 | this.propertyValueStrategy = propertyValueStrategy; 38 | } 39 | 40 | private String encrypt(byte[] bytes) { 41 | //Cipher 42 | byte[] encrypted = encryptor.encrypt(bytes); 43 | //Convert to base64 44 | return new String(Base64.encodeBase64(encrypted)); 45 | } 46 | 47 | @Override 48 | public void serialize(PropertyValue value, JsonGenerator gen, SerializerProvider provider) throws IOException { 49 | 50 | final ToXmlGenerator xmlGenerator = (ToXmlGenerator) gen; 51 | xmlGenerator.writeStartObject(); 52 | 53 | String stringToWrite = value.isProtected() ? 54 | encrypt(value.getValueAsBytes()) : 55 | value.getValueAsString(); 56 | 57 | if (value.isProtected()) { 58 | xmlGenerator.setNextIsAttribute(true); 59 | xmlGenerator.writeStringField("Protected", "True"); 60 | } 61 | xmlGenerator.setNextIsAttribute(false); 62 | xmlGenerator.setNextIsUnwrapped(true); 63 | xmlGenerator.writeStringField("text", stringToWrite); 64 | xmlGenerator.writeEndObject(); 65 | } 66 | } -------------------------------------------------------------------------------- /database/src/main/java/org/linguafranca/pwdb/StreamFormat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb; 18 | 19 | import org.linguafranca.pwdb.security.StreamEncryptor; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.io.OutputStream; 24 | 25 | /** 26 | * Interface provides for wrapping a database serialization in a stream format, e.g. KDBX or none. 27 | * 28 | * @author jo 29 | */ 30 | public interface StreamFormat { 31 | /** 32 | * Class allows for serializing a database directly to or from a stream with no encryption etc 33 | */ 34 | class None implements StreamFormat { 35 | 36 | @Override 37 | public void load(SerializableDatabase serializableDatabase, Credentials credentials, InputStream inputStream) throws IOException { 38 | serializableDatabase.setEncryption(new StreamEncryptor.None()); 39 | serializableDatabase.load(inputStream); 40 | inputStream.close(); 41 | } 42 | 43 | @Override 44 | public void save(SerializableDatabase serializableDatabase, Credentials credentials, OutputStream outputStream) throws IOException { 45 | serializableDatabase.setEncryption(new StreamEncryptor.None()); 46 | serializableDatabase.save(outputStream); 47 | outputStream.flush(); 48 | outputStream.close(); 49 | } 50 | 51 | @Override 52 | public StreamConfiguration.None getStreamConfiguration() { 53 | return new StreamConfiguration.None(); 54 | } 55 | 56 | @Override 57 | public void setStreamConfiguration(StreamConfiguration.None configuration) { 58 | 59 | } 60 | } 61 | 62 | void load(SerializableDatabase serializableDatabase, Credentials credentials, InputStream encryptedInputStream) throws IOException; 63 | 64 | void save(SerializableDatabase serializableDatabase, Credentials credentials, OutputStream encryptedOutputStream) throws IOException; 65 | 66 | C getStreamConfiguration(); 67 | 68 | void setStreamConfiguration(C configuration); 69 | } 70 | -------------------------------------------------------------------------------- /jaxb/src/test/java/org/linguafranca/pwdb/kdbx/jaxb/JaxbSaveAndReloadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.jaxb; 18 | 19 | import org.linguafranca.pwdb.Credentials; 20 | import org.linguafranca.pwdb.StreamFormat; 21 | import org.linguafranca.pwdb.checks.SaveAndReloadChecks; 22 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 23 | import org.linguafranca.pwdb.kdbx.KdbxHeader; 24 | 25 | import java.io.IOException; 26 | import java.io.InputStream; 27 | import java.io.OutputStream; 28 | 29 | /** 30 | * @author jo 31 | */ 32 | public class JaxbSaveAndReloadTest extends SaveAndReloadChecks { 33 | @Override 34 | public JaxbDatabase getDatabase() { 35 | return new JaxbDatabase(); 36 | } 37 | @Override 38 | public JaxbDatabase getDatabase(String name, Credentials credentials) throws IOException { 39 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream(name); 40 | return JaxbDatabase.load(credentials, inputStream); 41 | } 42 | 43 | @Override 44 | public void saveDatabase(JaxbDatabase database, Credentials credentials, OutputStream outputStream) throws IOException { 45 | database.save(credentials, outputStream); 46 | } 47 | 48 | @Override 49 | public JaxbDatabase loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 50 | return JaxbDatabase.load(credentials, inputStream); 51 | } 52 | 53 | @Override 54 | public Credentials getCreds(byte[] creds) { 55 | return new KdbxCreds(creds); 56 | } 57 | 58 | 59 | @Override 60 | public boolean verifyStreamFormat(StreamFormat s1, StreamFormat s2) { 61 | KdbxHeader h1 = (KdbxHeader) s1.getStreamConfiguration(); 62 | KdbxHeader h2 = (KdbxHeader) s1.getStreamConfiguration(); 63 | return (h1.getVersion() == h2.getVersion() && 64 | h1.getProtectedStreamAlgorithm().equals(h2.getProtectedStreamAlgorithm()) && 65 | h1.getKeyDerivationFunction().equals(h2.getKeyDerivationFunction()) && 66 | h1.getCipherAlgorithm().equals(h2.getCipherAlgorithm())); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /dom/src/test/java/org/linguafranca/pwdb/kdbx/dom/DomSaveAndReloadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdbx.dom; 18 | 19 | import org.linguafranca.pwdb.StreamFormat; 20 | import org.linguafranca.pwdb.checks.SaveAndReloadChecks; 21 | import org.linguafranca.pwdb.Database; 22 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 23 | import org.linguafranca.pwdb.Credentials; 24 | import org.linguafranca.pwdb.kdbx.KdbxHeader; 25 | 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.io.OutputStream; 29 | 30 | /** 31 | * @author jo 32 | */ 33 | public class DomSaveAndReloadTest extends SaveAndReloadChecks { 34 | 35 | @Override 36 | public Database getDatabase() { 37 | return new DomDatabaseWrapper(); 38 | } 39 | @Override 40 | public Database getDatabase(String name, Credentials credentials) throws IOException { 41 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream(name); 42 | return DomDatabaseWrapper.load(credentials, inputStream); 43 | } 44 | 45 | @Override 46 | public void saveDatabase(Database database, Credentials credentials, OutputStream outputStream) throws IOException { 47 | database.save(credentials, outputStream); 48 | } 49 | 50 | @Override 51 | public Database loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 52 | return DomDatabaseWrapper.load(credentials, inputStream); 53 | } 54 | 55 | @Override 56 | public Credentials getCreds(byte[] creds) { 57 | return new KdbxCreds("123".getBytes()); 58 | } 59 | 60 | @Override 61 | public boolean verifyStreamFormat(StreamFormat s1, StreamFormat s2) { 62 | KdbxHeader h1 = (KdbxHeader) s1.getStreamConfiguration(); 63 | KdbxHeader h2 = (KdbxHeader) s1.getStreamConfiguration(); 64 | return (h1.getVersion() == h2.getVersion() && 65 | h1.getProtectedStreamAlgorithm().equals(h2.getProtectedStreamAlgorithm()) && 66 | h1.getKeyDerivationFunction().equals(h2.getKeyDerivationFunction()) && 67 | h1.getCipherAlgorithm().equals(h2.getCipherAlgorithm())); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /kdb/src/main/java/org/linguafranca/pwdb/kdb/KdbCredentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Jo Rabin 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.linguafranca.pwdb.kdb; 18 | 19 | import com.google.common.io.ByteStreams; 20 | import org.linguafranca.pwdb.Credentials; 21 | import org.linguafranca.pwdb.security.Encryption; 22 | import org.bouncycastle.util.encoders.Hex; 23 | 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.security.MessageDigest; 27 | 28 | /** 29 | * Has inner classes representing credentials appropriate to KDB files 30 | * 31 | * @author jo 32 | */ 33 | public interface KdbCredentials extends Credentials { 34 | 35 | /** 36 | * Password only credentials 37 | */ 38 | class Password implements KdbCredentials { 39 | 40 | private final byte [] key; 41 | 42 | public Password(byte[] password) { 43 | MessageDigest md = Encryption.getSha256MessageDigestInstance(); 44 | this.key = md.digest(password); 45 | } 46 | 47 | @Override 48 | public byte[] getKey() { 49 | return key; 50 | } 51 | } 52 | 53 | /** 54 | * Key file credentials 55 | */ 56 | class KeyFile implements KdbCredentials { 57 | 58 | private final byte[] key; 59 | 60 | public KeyFile(byte[] password, InputStream inputStream) { 61 | MessageDigest md = Encryption.getSha256MessageDigestInstance(); 62 | byte[] pwKey = md.digest(password); 63 | md.update(pwKey); 64 | 65 | try { 66 | byte [] keyFileData = ByteStreams.toByteArray(inputStream); 67 | if (keyFileData.length == 64) { 68 | keyFileData = Hex.decode(keyFileData); 69 | key = md.digest(keyFileData); 70 | return; 71 | } 72 | throw new IllegalStateException("Invalid length key file " + keyFileData.length); 73 | } catch (IOException e) { 74 | throw new IllegalStateException("Could not read key file", e); 75 | } 76 | } 77 | 78 | @Override 79 | public byte[] getKey() { 80 | return this.key; 81 | } 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Use the latest 2.1 version of CircleCI pipeline process engine. 2 | # See: https://circleci.com/docs/2.0/configuration-reference 3 | version: 2.1 4 | 5 | # Define a job to be invoked later in a workflow. 6 | # See: https://circleci.com/docs/2.0/configuration-reference/#jobs 7 | jobs: 8 | # Below is the definition of your job to build and test your app, you can rename and customize it as you want. 9 | build-and-test-8: 10 | # These next lines define a Docker executor: https://circleci.com/docs/2.0/executor-types/ 11 | # You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub. 12 | # Be sure to update the Docker image tag below to openjdk version of your application. 13 | # A list of available CircleCI Docker Convenience Images are available here: https://circleci.com/developer/images/image/cimg/openjdk 14 | docker: 15 | - image: cimg/openjdk:8.0 16 | # Add steps to the job 17 | # See: https://circleci.com/docs/2.0/configuration-reference/#steps 18 | steps: 19 | # Checkout the code as the first step. 20 | - checkout 21 | # Use mvn clean and package as the standard maven build phase 22 | - run: 23 | name: Build 24 | command: mvn -B -DskipTests clean package 25 | # Then run your tests! 26 | - run: 27 | name: Test 28 | command: mvn -P inhibitConsoleOutput test 29 | 30 | build-and-test-11: 31 | # These next lines define a Docker executor: https://circleci.com/docs/2.0/executor-types/ 32 | # You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub. 33 | # Be sure to update the Docker image tag below to openjdk version of your application. 34 | # A list of available CircleCI Docker Convenience Images are available here: https://circleci.com/developer/images/image/cimg/openjdk 35 | docker: 36 | - image: cimg/openjdk:11.0 37 | # Add steps to the job 38 | # See: https://circleci.com/docs/2.0/configuration-reference/#steps 39 | steps: 40 | # Checkout the code as the first step. 41 | - checkout 42 | # Use mvn clean and package as the standard maven build phase 43 | - run: 44 | name: Build 45 | command: mvn -B -DskipTests clean package 46 | # Then run your tests! 47 | - run: 48 | name: Test 49 | command: mvn -P inhibitConsoleOutput test 50 | 51 | # Invoke jobs via workflows 52 | # See: https://circleci.com/docs/2.0/configuration-reference/#workflows 53 | workflows: 54 | build-8-11: # This is the name of the workflow, feel free to change it to better match your workflow. 55 | # Inside the workflow, you define the jobs you want to run. 56 | jobs: 57 | - build-and-test-8 58 | - build-and-test-11 59 | -------------------------------------------------------------------------------- /example/src/test/java/org/linguafranca/pwdb/kdbx/validation/Issue27Test.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.validation; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.junit.Ignore; 5 | import org.junit.Test; 6 | import org.linguafranca.pwdb.kdbx.Helpers; 7 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 8 | import org.linguafranca.pwdb.kdbx.KdbxHeader; 9 | import org.linguafranca.pwdb.kdbx.KdbxSerializer; 10 | import org.linguafranca.pwdb.kdbx.jaxb.JaxbDatabase; 11 | import org.linguafranca.pwdb.kdbx.jaxb.JaxbEntry; 12 | 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.io.InputStreamReader; 16 | import java.io.PrintStream; 17 | import java.nio.charset.StandardCharsets; 18 | import java.util.List; 19 | 20 | import static org.junit.Assert.assertEquals; 21 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 22 | 23 | public class Issue27Test { 24 | static PrintStream printStream = getTestPrintStream(); 25 | /** 26 | * Check load of problem file 27 | */ 28 | @Test 29 | public void testIssue27() throws IOException { 30 | InputStream is = this.getClass().getClassLoader().getResourceAsStream("issue-27/bogus-timestamp2.kdbx"); 31 | KdbxCreds creds = new KdbxCreds("passwordless".getBytes()); 32 | JaxbDatabase db = JaxbDatabase.load(creds, is); 33 | List entries = db.findEntries("testtitle"); 34 | 35 | for (JaxbEntry entry: entries) { 36 | printStream.println(Helpers.fromDateV3(entry.getCreationTime())); 37 | assertEquals("2021-01-11T09:18:56Z", Helpers.fromDateV3(entry.getCreationTime())); 38 | } 39 | } 40 | 41 | /** 42 | * Verify that V4 dates are still processed correctly 43 | */ 44 | @Test 45 | public void testV4Date() throws IOException { 46 | InputStream is = this.getClass().getClassLoader().getResourceAsStream("V4-AES-AES.kdbx"); 47 | KdbxCreds creds = new KdbxCreds("123".getBytes()); 48 | JaxbDatabase db = JaxbDatabase.load(creds, is); 49 | List entries = db.findEntries("Sample Entry #2 - Copy"); 50 | 51 | for (JaxbEntry entry: entries) { 52 | printStream.println(Helpers.fromDate(entry.getCreationTime())); 53 | assertEquals("2018-01-26T13:20:58Z", Helpers.fromDateV3(entry.getCreationTime())); 54 | } 55 | } 56 | 57 | @Test @Ignore 58 | public void testIssue27XML() throws IOException { 59 | 60 | InputStream is = this.getClass().getClassLoader().getResourceAsStream("issue-27/bogus-timestamp2.kdbx"); 61 | KdbxCreds creds = new KdbxCreds("passwordless".getBytes()); 62 | InputStream plainText = KdbxSerializer.createUnencryptedInputStream(creds,new KdbxHeader(), is); 63 | printStream.println(CharStreams.toString(new InputStreamReader(plainText, StandardCharsets.UTF_8))); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /simple/src/main/java/org/linguafranca/pwdb/kdbx/simple/converter/ValueConverter.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.simple.converter; 2 | 3 | import org.apache.commons.codec.binary.Base64; 4 | import org.linguafranca.pwdb.kdbx.simple.model.EntryClasses; 5 | import org.linguafranca.pwdb.security.StreamEncryptor; 6 | import org.simpleframework.xml.convert.Converter; 7 | import org.simpleframework.xml.stream.InputNode; 8 | import org.simpleframework.xml.stream.OutputNode; 9 | 10 | import java.nio.charset.StandardCharsets; 11 | import java.util.Objects; 12 | 13 | /** 14 | * Value converter takes care of encryption and decryption of protected fields 15 | */ 16 | public class ValueConverter implements Converter { 17 | 18 | private final StreamEncryptor encryption; 19 | 20 | public ValueConverter(StreamEncryptor encryption) { 21 | this.encryption = encryption; 22 | } 23 | 24 | /** 25 | * De-serialise (unmarshal) the input node 26 | * @param node this is the node to deserialize the object from 27 | * 28 | * @return the de-serialised object 29 | */ 30 | @Override 31 | public EntryClasses.StringProperty.Value read(InputNode node) throws Exception { 32 | EntryClasses.StringProperty.Value value = new EntryClasses.StringProperty.Value(); 33 | if (Objects.nonNull(node.getAttribute("Protected")) && node.getAttribute("Protected").getValue().equals("True")) { 34 | byte[] encrypted = new byte[0]; 35 | // you can only read the value once 36 | String text = node.getValue(); 37 | if (Objects.nonNull(text)) { 38 | encrypted = Base64.decodeBase64(text.getBytes()); 39 | } 40 | String decrypted = new String(encryption.decrypt(encrypted), StandardCharsets.UTF_8); 41 | value.setText(decrypted); 42 | value.setProtected(null); 43 | value.setProtectOnOutput(true); 44 | } else { 45 | value.setProtectOnOutput(false); 46 | value.setText(node.getValue()); 47 | } 48 | return value; 49 | } 50 | 51 | /** 52 | * Serialise (marshal) the object 53 | * @param node this is the node to serialized the object to 54 | * @param value this is the value that is to be serialized 55 | */ 56 | @Override 57 | public void write(OutputNode node, EntryClasses.StringProperty.Value value) throws Exception { 58 | if (value.getProtectOnOutput()) { 59 | byte [] encrypted = encryption.encrypt(value.getText().getBytes(StandardCharsets.UTF_8)); 60 | byte [] base64Encoded = Base64.encodeBase64(encrypted); 61 | node.setValue(new String(base64Encoded)); 62 | node.getAttributes().put("Protected", "True"); 63 | } else { 64 | node.setValue(value.getText()); 65 | } 66 | //node.getAttributes().remove("protectInMemory"); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /jaxb/bindings.xml: -------------------------------------------------------------------------------- 1 | 16 | 19 | 22 | 23 | 24 | 28 | 29 | 30 | 34 | 35 | 36 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | This class, while generated, is not used see {@link 49 | org.linguafranca.pwdb.kdbx.jaxb.org.linguafranca.pwdb.base.AbstractJaxbParentedBinding} which is the 50 | actual implementation class. 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /example/src/main/java/org/linguafranca/pwdb/kdbx/ChooseFile.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx; 2 | 3 | import com.google.common.base.Strings; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import javax.swing.*; 8 | import javax.swing.filechooser.FileFilter; 9 | import java.io.*; 10 | import java.net.URL; 11 | import java.nio.charset.Charset; 12 | import java.nio.file.Files; 13 | import java.nio.file.Paths; 14 | 15 | import static org.linguafranca.pwdb.kdbx.Util.streamToString; 16 | 17 | /** 18 | * Utility to allow browsing of database files and listing content to console 19 | */ 20 | public class ChooseFile { 21 | 22 | public static void main(String[] args) throws IOException { 23 | ChooseFile cf = new ChooseFile(); 24 | cf.choose(); 25 | } 26 | 27 | Logger logger = LoggerFactory.getLogger(this.getClass()); 28 | 29 | public ChooseFile(){ 30 | 31 | } 32 | public void choose() throws IOException { 33 | final JFileChooser fc = new JFileChooser(); 34 | // get a file in the test resource directory 35 | URL resources = this.getClass().getClassLoader().getResource("kdb.key"); 36 | try { 37 | fc.setCurrentDirectory(Paths.get(resources.toURI()).toFile()); 38 | } catch (Exception e) { 39 | throw new RuntimeException(e); 40 | } 41 | fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 42 | fc.setFileFilter(new FileFilter() { 43 | @Override 44 | public boolean accept(File f) { 45 | return f.getName().endsWith(".kdbx"); 46 | } 47 | 48 | @Override 49 | public String getDescription() { 50 | return "KDBX Database"; 51 | } 52 | }); 53 | 54 | int returnVal = fc.showOpenDialog(null); 55 | if (returnVal == JFileChooser.APPROVE_OPTION) { 56 | String s = (String)JOptionPane.showInputDialog( 57 | null, 58 | "Enter the password for " + fc.getSelectedFile().getName(), 59 | "Password", 60 | JOptionPane.PLAIN_MESSAGE, 61 | null, 62 | null, 63 | "123"); 64 | if (Strings.isNullOrEmpty(s)) { 65 | return; 66 | } 67 | logger.info("Opening {}", fc.getSelectedFile().getPath()); 68 | try (InputStream is = Files.newInputStream(Paths.get(fc.getSelectedFile().getPath()))) { 69 | InputStream ss = KdbxSerializer.createUnencryptedInputStream(new KdbxCreds(s.getBytes()), new KdbxHeader(), is); 70 | System.out.println(streamToString(ss)); 71 | System.out.println(); 72 | System.out.flush(); 73 | } 74 | /* try (InputStream is = Files.newInputStream(Paths.get(fc.getSelectedFile().getPath()))) { 75 | HexViewer.list(is); 76 | }*/ 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /jackson/src/test/java/org/linguafranca/pwdb/JacksonDatabaseLoadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb; 17 | 18 | import java.io.InputStream; 19 | import java.io.PrintStream; 20 | 21 | import org.junit.Test; 22 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 23 | import org.linguafranca.pwdb.kdbx.jackson.JacksonDatabase; 24 | 25 | import static org.linguafranca.test.util.TestUtil.getTestPrintStream; 26 | 27 | public class JacksonDatabaseLoadTest { 28 | 29 | static PrintStream printStream = getTestPrintStream(); 30 | 31 | 32 | @Test 33 | public void loadXml() throws Exception { 34 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("ExampleDatabase.xml"); 35 | JacksonDatabase database = JacksonDatabase.loadXml(inputStream); 36 | database.visit(new Visitor.Print(printStream)); 37 | } 38 | @Test 39 | public void loadKdbx() throws Exception { 40 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("test123.kdbx"); 41 | JacksonDatabase database = JacksonDatabase.load(new KdbxCreds("123".getBytes()), inputStream); 42 | database.visit(new Visitor.Print(printStream)); 43 | } 44 | 45 | @Test 46 | public void loadKdbxV4() throws Exception { 47 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("V4-AES-Argon2.kdbx"); 48 | JacksonDatabase database = JacksonDatabase.load(new KdbxCreds("123".getBytes()), inputStream); 49 | database.visit(new Visitor.Print(printStream)); 50 | // test what happens to dates in V4 51 | database.visit(new Visitor.Default(){ 52 | @Override 53 | public void visit(Entry entry) { 54 | printStream.println(entry.getCreationTime()); 55 | } 56 | }); 57 | } 58 | 59 | @Test 60 | public void emptyDb() throws Exception { 61 | JacksonDatabase database = new JacksonDatabase(); 62 | printStream.println(database.getDescription()); 63 | } 64 | 65 | @Test 66 | public void dbWithDeleted() throws Exception { 67 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream("testDeleted.kdbx"); 68 | JacksonDatabase database = JacksonDatabase.load(new KdbxCreds("123".getBytes()), inputStream); 69 | database.visit(new Visitor.Print(printStream)); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /example/src/test/java/org/linguafranca/pwdb/kdbx/validation/Issue33Test.java: -------------------------------------------------------------------------------- 1 | package org.linguafranca.pwdb.kdbx.validation; 2 | 3 | 4 | import org.junit.Before; 5 | import org.junit.BeforeClass; 6 | import org.junit.Test; 7 | import org.linguafranca.pwdb.Credentials; 8 | import org.linguafranca.pwdb.StreamFormat; 9 | import org.linguafranca.pwdb.kdbx.Helpers; 10 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 11 | import org.linguafranca.pwdb.kdbx.Util; 12 | import org.linguafranca.pwdb.kdbx.dom.DomDatabaseWrapper; 13 | import org.linguafranca.pwdb.kdbx.jackson.JacksonDatabase; 14 | import org.linguafranca.pwdb.kdbx.jaxb.JaxbDatabase; 15 | import org.linguafranca.pwdb.kdbx.simple.SimpleDatabase; 16 | 17 | import java.io.*; 18 | import java.nio.file.Files; 19 | import java.nio.file.Paths; 20 | 21 | /** 22 | * Review Issue-33 https://github.com/jorabin/KeePassJava2/issues/33 23 | */ 24 | public class Issue33Test { 25 | 26 | public static final String TEST_RESOURCE = "V4-AES-Argon2-CustomIcon.kdbx"; 27 | public static final String TEST_OUTPUT_DIR = "testOutput"; 28 | public static final File TEST_XML_FILE = Paths.get(TEST_OUTPUT_DIR,"Issue33Source.xml").toFile(); 29 | public static final KdbxCreds CREDENTIALS = new KdbxCreds("123".getBytes()); 30 | 31 | 32 | InputStream inputStream; 33 | 34 | @BeforeClass 35 | public static void listXml() throws IOException { 36 | Files.createDirectories(Paths.get(TEST_OUTPUT_DIR)); 37 | Util.listXml(TEST_RESOURCE, CREDENTIALS, new PrintWriter(TEST_XML_FILE)); 38 | Helpers.isV4.set(true); 39 | } 40 | 41 | @Before 42 | public void refreshInputStream() { 43 | inputStream = this.getClass().getClassLoader().getResourceAsStream(TEST_RESOURCE); 44 | } 45 | 46 | @Test 47 | public void testDomDatabaseWrapper() throws IOException { 48 | DomDatabaseWrapper database = DomDatabaseWrapper.load(CREDENTIALS, inputStream); 49 | database.save(new StreamFormat.None(), new Credentials.None(), Files.newOutputStream(Paths.get(TEST_OUTPUT_DIR, "Issue33Dom.xml"))); 50 | } 51 | 52 | @Test 53 | public void testJaxbDatabase() throws IOException { 54 | JaxbDatabase database = JaxbDatabase.load(CREDENTIALS, inputStream); 55 | database.save(new StreamFormat.None(), new Credentials.None(), Files.newOutputStream(Paths.get(TEST_OUTPUT_DIR, "Issue33Jaxb.xml"))); 56 | } 57 | 58 | @Test 59 | public void testSimpleDatabase() throws IOException { 60 | SimpleDatabase database = SimpleDatabase.load(CREDENTIALS, inputStream); 61 | database.save(new StreamFormat.None(), new Credentials.None(), Files.newOutputStream(Paths.get(TEST_OUTPUT_DIR, "Issue33Simple.xml"))); 62 | } 63 | 64 | @Test 65 | public void testJacksonDatabase() throws IOException { 66 | JacksonDatabase database = JacksonDatabase.load(CREDENTIALS, inputStream); 67 | database.save(new StreamFormat.None(), new Credentials.None(), Files.newOutputStream(Paths.get(TEST_OUTPUT_DIR, "Issue33Jackson.xml"))); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /jackson/src/main/java/org/linguafranca/pwdb/kdbx/jackson/converter/ValueDeserializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb.kdbx.jackson.converter; 17 | 18 | import com.fasterxml.jackson.core.JsonParser; 19 | import com.fasterxml.jackson.databind.DeserializationContext; 20 | import com.fasterxml.jackson.databind.JsonNode; 21 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 22 | import org.apache.commons.codec.binary.Base64; 23 | import org.linguafranca.pwdb.Database; 24 | import org.linguafranca.pwdb.PropertyValue; 25 | import org.linguafranca.pwdb.kdbx.Helpers; 26 | import org.linguafranca.pwdb.kdbx.jackson.model.EntryClasses; 27 | import org.linguafranca.pwdb.security.StreamEncryptor; 28 | 29 | import java.io.IOException; 30 | import java.nio.charset.StandardCharsets; 31 | 32 | public class ValueDeserializer extends StdDeserializer { 33 | 34 | private final StreamEncryptor encryptor; 35 | private final PropertyValue.Strategy strategy; 36 | 37 | public ValueDeserializer(StreamEncryptor encryptor, PropertyValue.Strategy strategy) { 38 | super(ValueDeserializer.class); 39 | this.encryptor = encryptor; 40 | this.strategy = strategy; 41 | } 42 | 43 | @Override 44 | public PropertyValue deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 45 | 46 | JsonNode node = p.getCodec().readTree(p); 47 | 48 | if (node.isTextual()) { 49 | return strategy.newUnprotected().of(node.textValue()); 50 | } 51 | 52 | if (node.isObject()) { 53 | // TODO not clear what is happening here, looks like it's not exactly correct 54 | //We need to decrypt all Protected values 55 | String cipherText = ""; 56 | if (node.has("")) { 57 | cipherText = node.get("").asText(); 58 | } 59 | 60 | if (node.has("Protected") && Boolean.TRUE.equals(Helpers.toBoolean(node.get("Protected").asText()))) { 61 | //Decode to byte the Base64 text 62 | byte[] encrypted = Base64.decodeBase64(cipherText.getBytes()); 63 | byte[] decrypted = encryptor.decrypt(encrypted); 64 | return strategy.newProtected().of(decrypted); 65 | } 66 | return strategy.newUnprotected().of(cipherText); 67 | } 68 | 69 | throw new IllegalStateException("Error parsing XML node type is " + node.getClass()); 70 | } 71 | } -------------------------------------------------------------------------------- /jackson/src/test/java/org/linguafranca/pwdb/JacksonSaveAndReloadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Giuseppe Valente 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.linguafranca.pwdb; 17 | 18 | import static org.junit.Assert.assertTrue; 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.io.OutputStream; 23 | 24 | import org.linguafranca.pwdb.checks.SaveAndReloadChecks; 25 | import org.linguafranca.pwdb.kdbx.KdbxCreds; 26 | import org.linguafranca.pwdb.kdbx.KdbxHeader; 27 | 28 | import org.linguafranca.pwdb.kdbx.jackson.JacksonDatabase; 29 | import org.linguafranca.pwdb.kdbx.jackson.JacksonEntry; 30 | import org.linguafranca.pwdb.kdbx.jackson.JacksonGroup; 31 | import org.linguafranca.pwdb.kdbx.jackson.JacksonIcon; 32 | 33 | 34 | public class JacksonSaveAndReloadTest extends SaveAndReloadChecks{ 35 | 36 | @Override 37 | public JacksonDatabase getDatabase() { 38 | try { 39 | return new JacksonDatabase(); 40 | } catch(Exception e) { 41 | return null; 42 | } 43 | 44 | } 45 | 46 | @Override 47 | public JacksonDatabase getDatabase(String name, Credentials credentials) throws IOException { 48 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream(name); 49 | return JacksonDatabase.load(credentials, inputStream); 50 | } 51 | 52 | @Override 53 | public void saveDatabase(JacksonDatabase database, Credentials credentials, OutputStream outputStream) throws IOException { 54 | database.save(credentials, outputStream); 55 | } 56 | 57 | @Override 58 | public JacksonDatabase loadDatabase(Credentials credentials, InputStream inputStream) throws IOException { 59 | return JacksonDatabase.load(credentials, inputStream); 60 | } 61 | 62 | 63 | @Override 64 | public boolean verifyStreamFormat(StreamFormat s1, StreamFormat s2) { 65 | KdbxHeader h1 = (KdbxHeader) s1.getStreamConfiguration(); 66 | KdbxHeader h2 = (KdbxHeader) s1.getStreamConfiguration(); 67 | return (h1.getVersion() == h2.getVersion() && 68 | h1.getProtectedStreamAlgorithm().equals(h2.getProtectedStreamAlgorithm()) && 69 | h1.getKeyDerivationFunction().equals(h2.getKeyDerivationFunction()) && 70 | h1.getCipherAlgorithm().equals(h2.getCipherAlgorithm())); 71 | } 72 | 73 | 74 | @Override 75 | public Credentials getCreds(byte[] creds) { 76 | return new KdbxCreds(creds); 77 | } 78 | 79 | } 80 | --------------------------------------------------------------------------------