{"id":36420110,"url":"https://github.com/antfarmer/easyjce","last_synced_at":"2026-01-11T17:05:47.788Z","repository":{"id":57738392,"uuid":"148435288","full_name":"antfarmer/easyjce","owner":"antfarmer","description":"EasyJCE provides an easy to use interface for encrypting, decrypting, and hashing data for transmission or storage using the Java Cryptographic Extension (JCE).","archived":false,"fork":false,"pushed_at":"2024-10-17T05:38:38.000Z","size":35276,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2024-10-20T06:03:14.604Z","etag":null,"topics":["argon2","bouncy-castle","cryptography","cryptography-library","cryptography-tools","encryption","hashing","hibernate","java","password","password-hasher","spring-security"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/antfarmer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-09-12T06:51:24.000Z","updated_at":"2024-10-17T05:20:20.000Z","dependencies_parsed_at":"2022-08-26T12:33:19.503Z","dependency_job_id":null,"html_url":"https://github.com/antfarmer/easyjce","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/antfarmer/easyjce","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antfarmer%2Feasyjce","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antfarmer%2Feasyjce/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antfarmer%2Feasyjce/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antfarmer%2Feasyjce/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/antfarmer","download_url":"https://codeload.github.com/antfarmer/easyjce/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antfarmer%2Feasyjce/sbom","scorecard":{"id":198668,"data":{"date":"2025-08-11","repo":{"name":"github.com/antfarmer/easyjce","commit":"e68e773f6321d154ba278fa971b80e03f2a7e7fa"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.4,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":9,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/gradle.yml:21","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/gradle.yml:63","Warn: no topLevel permission defined: .github/workflows/gradle.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":8,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1","Warn: binary detected: lib/test/antfarmer-common_app.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":5,"reason":"dependency not pinned by hash detected -- score normalized to 5","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/antfarmer/easyjce/gradle.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/antfarmer/easyjce/gradle.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/gradle.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/antfarmer/easyjce/gradle.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:66: update your workflow using https://app.stepsecurity.io/secureworkflow/antfarmer/easyjce/gradle.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:68: update your workflow using https://app.stepsecurity.io/secureworkflow/antfarmer/easyjce/gradle.yml/master?enable=pin","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   2 out of   3 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-16T22:20:37.118Z","repository_id":57738392,"created_at":"2025-08-16T22:20:37.118Z","updated_at":"2025-08-16T22:20:37.118Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28314264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T14:58:17.114Z","status":"ssl_error","status_checked_at":"2026-01-11T14:55:53.580Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["argon2","bouncy-castle","cryptography","cryptography-library","cryptography-tools","encryption","hashing","hibernate","java","password","password-hasher","spring-security"],"created_at":"2026-01-11T17:05:47.723Z","updated_at":"2026-01-11T17:05:47.779Z","avatar_url":"https://github.com/antfarmer.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EasyJCE\n\n![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/antfarmer/easyjce/gradle.yml)\n[![codecov](https://codecov.io/gh/antfarmer/easyjce/branch/master/graph/badge.svg)](https://codecov.io/gh/antfarmer/easyjce)\n[![Maven Central](https://img.shields.io/maven-central/v/org.antfarmer/easyjce.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22org.antfarmer%22%20AND%20a:%22easyjce%22)\n[![License](https://img.shields.io/badge/License-Apache%202.0-purple.svg)](/LICENSE)\n\n**EasyJCE** provides an easy to use interface for encrypting, decrypting, and hashing data for transmission or storage using the Java Cryptographic Extension (JCE). A set of Hibernate user types is included to transparently integrate encryption into the data layer in a JPA/Hibernate environment, ensuring data is persisted in its encrypted form while obscuring encryption and decryption logic from application code. EasyJCE supports most algorithms implemented for the JCE, including those provided by third-party encryption service providers. Integrated MAC (Message Authentication Code) support can optionally be used to ensure data integrity and indicate possible data tampering. EasyJCE also provides basic encoding and decoding facilities for transmitting encrypted binary data through mediums which are limited to printable ASCII characters, such as email messages or URL's.\n\n## For the Impatient\n- [Here's](#programmatic-encryption) how to encrypt programmatically\n- [Here's](#declarative-encryption-via-hibernate-usertype-annotations) how to encrypt POJO fields using annotations\n- [Here's](#encryption-via-hibernate-usertype-using-xml-configuration) how to encrypt POJO fields using XML\n- [Here's](#programmatic-password-encoding) how to hash passwords programmatically\n- [Here's](#declarative-password-encoding-via-hibernate-usertype-annotations) how to hash password POJO fields using annotations\n- [Here's](#password-encoding-via-hibernate-usertype-using-xml-configuration) how to hash password POJO fields using XML\n\n## Contents\n- [Installation](#installation)\n  - [Maven](#maven)\n  - [Gradle](#gradle)\n  - [Required Libraries](#required-libraries)\n- [Usage](#usage)\n  - [TextEncoder](#textencoder)\n  - [Keys](#keys)\n  - [Encryption](#encryption)\n    - [Programmatic encryption](#programmatic-encryption)\n    - [Declarative encryption via Hibernate UserType annotations](#declarative-encryption-via-hibernate-usertype-annotations)\n    - [Encryption via Hibernate UserType using XML configuration](#encryption-via-hibernate-usertype-using-xml-configuration)\n  - [Password Encoding (Hashing)](#password-encoding-hashing)\n    - [Programmatic password encoding](#programmatic-password-encoding)\n    - [Declarative password encoding via Hibernate UserType annotations](#declarative-password-encoding-via-hibernate-usertype-annotations)\n    - [Password encoding via Hibernate UserType using XML configuration](#password-encoding-via-hibernate-usertype-using-xml-configuration)\n- [API Documentation](#api-documentation)\n\n## Installation\n### Maven\nAdd this to `pom.xml` within the `dependencies` tag:\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003eorg.antfarmer\u003c/groupId\u003e\n\t\u003cartifactId\u003eeasyjce\u003c/artifactId\u003e\n\t\u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n### Gradle\nAdd this to `build.gradle` in the `dependencies` block:\n```groovy\n\tcompile 'org.antfarmer:easyjce:1.1.0'\n```\n### Required Libraries\nWhile the compile-time and testing dependencies are documented in the provided pom file, technically, there are no runtime dependencies for encryption. Here is a summary of the optional runtime requirements depending on the features needed:\n\n- Hibernate: integration with Hibernate's UserType interface for applying encryption/hashing to POJO fields\n- Bouncy Castle: password encoding and as a custom JCE provider\n- Spring Security Crypto: password encoding\n- Argon2Jvm: Argon2 encoding capabilities\n\nTesting requires slf4j, logback, easymock, junit, and h2 db\n\n\n## Usage\nPlease have a look at the [API documentation](https://antfarmer.github.io/easyjce/).\n\n### TextEncoder\nTextEncoder's are responsible for encoding/decoding binary data to/from ASCII-based String forms which allow you to specify keys in configuration and encrypted/hashed data in normal varchar/text database columns. \n\nThese include Hex, Base32, and Base64 implementations, with variations for the alphabet used, depending on the application. For example, BASE64 uses `'+'` and `'/'` for encoding which are not allowed in URL parameters. The `Base64UrlEncoder` replaces these with `'-'` and `'.'` which are allowed. The default recommendation is for the `Base64Encoder`.\n\n### Keys\nIn most cases, you first will need to generate some keys for encryption, unless you are using a hashing algorithm. Use methods on `CryptoUtil` to generate the keys you want.\n\nFor example, this creates a key for AES-256:\n```java\n\tSecretKey key = CryptoUtil.generateSecretKey(AesParameters.KEY_SIZE_256, AesParameters.ALGORITHM_AES);\n\tString keyCfgValue = Base64Encoder.getInstance().encode(key.getEncoded());\n\tSystem.out.println(keyCfgValue);\n```\n\nThis creates an asymmetric key pair for RSA-1024:\n```java\n\tKeyPair pair = CryptoUtil.generateAsymmetricKeyPair(RsaParameters.KEY_SIZE_1024, RsaParameters.ALGORITHM_RSA);\n\tString pubKeyCfgValue = Base64Encoder.getInstance().encode(pair.getPublic().getEncoded());\n\tString privKeyCfgValue = Base64Encoder.getInstance().encode(pair.getPrivate().getEncoded());\n\tSystem.out.println(pubKeyCfgValue);\n\tSystem.out.println(privKeyCfgValue);\n```\nOverloaded methods allow for use of non-default JCE Provider such as Bouncy-Castle, etc.\n\nKeys will be used to configure your encryptors below and can be defined in a number of ways:\n- passing a `Key` instance programmatically\n- encoded string parameter\n- passing the class name of a `KeyLoader` implementation which loads a key in any way you choose and/or from various sources\n\n### Encryption\nEncryptors allow you to encrypt and decrypt information using specified algorithms, block modes, padding, and HMAC schemes. These types of \nalgorithms are reversible, so that the sensitive data can be recovered for later use. This is appropriate for storing credentials that must be\nused in their original form later on, but not for storing credentials for the given application as it need not be transmitted. See the \n[Password Encoding section](#password-encoding-hashing) below for one-way hashing algorithms.\n\nEncryptors can be created programmatically or defined via configuration (annotations or XML). System properties may also be used by specifying the system property prefix and organizing the appropriate encryption properties under that prefix. Encryptors can also be 'registered' for use JVM-wide using the `EncryptorStore` class. This can be helpful when trying to control the number of instances created through Hibernate mappings by creating them programmatically and referencing them by name in configuration.\n\n#### Programmatic encryption\nEncryption can be performed programmatically by creating an instance of `AlgorithmParameters` which can then be applied to an `Encryptor`.\nHere's an example for setting up AES-256-ECB with HMAC-SHA1:\n(Note: use of the `Base64Encoder` in the parameters constructor which is used to decode the key in the parameters,\n\twhile the `Base64Encoder` in the encryptor constructor controls how encrypted values are encoded).\n```java\n\tfinal AesParameters parameters = new AesParameters(Base64Encoder.getInstance())\n\t\t.setKey(\"GsqGjFpSQe0D+8nKLmOoFA2/mfXHzFbYXWwAyxmxhjo\")\n\t\t.setBlockMode(AesParameters.BLOCK_MODE_ECB)\n\t\t.setPadding(AesParameters.PADDING_PKCS5)\n\t\t.setMacAlgorithm(AesParameters.MAC_ALGORITHM_HMAC_SHA1)\n\t\t.setMacKeySize(AesParameters.MAC_KEY_SIZE_128)\n\t;\n\tfinal Encryptor encryptor = new Encryptor(Base64Encoder.getInstance()).setAlgorithmParameters(parameters);\n\tencryptor.initialize();\n\tfinal String encrypted = encryptor.encrypt(\"secret stuff\");\n\tSystem.out.println(\"Encrypted: \" + encrypted);\n\tfinal String decrypted = encryptor.decrypt(encrypted);\n\tSystem.out.println(\"Decrypted: \" + decrypted);\n```\nThe `Encryptor` can now be used to encrypt/decrypt values and objects as needed.\n\n#### Declarative encryption via Hibernate UserType annotations\nIn a JPA/Hibernate environment, encryption can be declared on POJO's using annotations. This allows for encryption of the field value as it is persisted to the database, and decryption as it is read from the database back into the POJO. This allows transparent handling of sensitive data within your application.\n\nHere is an example for AES-256-GCM: (GCM negates the need for a HMAC)\n```java\n\t@Type(type = \"org.antfarmer.ejce.hibernate.EncryptedStringType\", parameters = {\n\t\t@Parameter(name = \"paramClass\", value = \"org.antfarmer.ejce.parameter.AesParameters\"),\n\t\t@Parameter(name = \"paramEncoder\", value = \"org.antfarmer.ejce.encoder.Base64Encoder\"),\n\t\t@Parameter(name = \"blockMode\", value = \"GCM\"),\n\t\t@Parameter(name = \"key\", value = \"th8k9z2PCO9apj1GSYU86t5DP9dfmG7uRkfdGSWrnJ0\"),\n\t\t@Parameter(name = \"encoder\", value = \"org.antfarmer.ejce.encoder.Base64Encoder\")\n\t})\n\tpublic String getSecretValue() {\n\t\treturn secretValue;\n\t}\n```\n\nHere is an example for referencing a pre-configured encryptor in the `EncryptorStore`:\n```java\n\t... // in some bootstrap class\n\tEncryptoreStore.add(\"com.myapp.enc.secretEncryptor\", mySecretEncryptor);\n\t... // in POJO\n\t@Type(type = \"org.antfarmer.ejce.hibernate.EncryptedStringType\", parameters = {\n\t\t@Parameter(name = \"storeKey\", value = \"com.myapp.enc.secretEncryptor\")\n\t})\n\tpublic String getSecretValue() {\n\t\treturn secretValue;\n\t}\n```\nIt is up to you to choose the appropriate `AbstractHibernateType`, but `EncryptedStringType` is by far the most common.\nMore possible parameter keys and values can found in `ConfigurerUtil` and the appropriate `AlgorithmParameters` classes.\n\n#### Encryption via Hibernate UserType using XML configuration\nIn a JPA/Hibernate environment, encryption can also be configured via mapping XML. This allows for encryption of the field value as it is persisted to the database, and decryption as it is read from the database back into the POJO. This allows transparent handling of sensitive data within your application.\n\nHere is an example for AES-256-GCM: (GCM negates the need for a HMAC)\n```xml\n\u003chibernate-mapping\u003e\n\t\u003ctypedef name=\"encryptedPassword\" class=\"org.antfarmer.ejce.hibernate.EncryptedStringType\"\u003e\n\t\t\u003cparam name=\"paramClass\"\u003eorg.antfarmer.ejce.parameter.AesParameters\u003c/param\u003e\n\t\t\u003cparam name=\"paramEncoder\"\u003eorg.antfarmer.ejce.encoder.Base64Encoder\u003c/param\u003e\n\t\t\u003cparam name=\"key\"\u003ejlor+XrLXfT2ytV5lpQN0Q\u003c/param\u003e\n\t\t\u003cparam name=\"macAlgorithm\"\u003eHmacSHA1\u003c/param\u003e\n\t\t\u003cparam name=\"macKey\"\u003efZB8/kF5BPKB/0bCiR+Rxg\u003c/param\u003e\n\t\u003c/typedef\u003e\n\t...\n\t\u003cclass name=\"...\"\u003e\n\t\t...\n\t\t\u003cproperty name=\"password\" type=\"encryptedPassword\"/\u003e\n\t\t...\n\t\u003c/class\u003e\n\u003c/hibernate-mapping\u003e\n```\nIt is up to you to choose the appropriate `AbstractHibernateType`, but `EncryptedStringType` is by far the most common.\nMore possible parameter keys and values can found in `ConfigurerUtil` and the appropriate `AlgorithmParameters` classes.\n\n\n### Password Encoding (Hashing)\nPassword encoders are used to encode private information that only needs to be matched later on. Because these algorithms are essentially one-way functions, the original information cannot be deciphered afterward, at least without a huge amount of computing power. This is perfect for application credentials that only need to be matched, not re-transmitted to any other service later on.\n\nIt is recommended to test the chosen algorithm and parameters on the applicable environments so that each hashing operation takes somewhere between 50 and 500ms, depending on the security and user experience constraints of your application. Certain algorithms also allow memory usage configuration. This can be important to adjust when weighing system performance vs. security level in preventing GPU-based brute-force attacks.\n\nAs with encryptors, password encoders can be created programmatically or defined via configuration (annotations or XML). System properties may also be used by specifying the system property prefix and organizing the appropriate password encoder properties under that prefix. Password encoders can also be 'registered' for use JVM-wide using the `PasswordEncoderStore` class. This can be helpful when trying to control the number of instances created through Hibernate mappings by creating them programmatically and referencing them by name in configuration.\n\nAs hashing algorithms age, there will eventually be a point where you will need to upgrade the chosen encoding scheme. Since these passwords cannot be deciphered, you will not be able to upgrade them altogether in a maintenance operation. You can simply change the algorithm configured for your POJO to ensure all new users and existing users' password updates are using the new scheme. In order to allow access to existing users, you will either need to check more than one algorithm in the credential verification logic, or predetermine the password encoding scheme by looking at the encoded form. A useful feature for handling this is the \"prefix\" property which allows you to prefix the encoded value with the given hash scheme prefix. Most schemes already encode the parameters of the algorithm such as strength and iteration count, but it might be wise to at least indicate the scheme here, e.g. '{pbkdf2}' or '{bcrypt}', etc. The key is defined in `AbstractConfigurablePasswordEncoder.KEY_PREFIX`.\n\n#### Programmatic password encoding\nPassword encoding can be performed programmatically by creating an instance of `PasswordEncoder` and setting up the specific parameters if the defaults are not sufficient.\nHere's an example for setting up PBKDF2 with secret:\n(Note: parameter values are optional overrides of defaults. Also note that values must be Strings).\n```java\n\tfinal Class\u003c? extends Provider\u003e providerClass = BouncyCastleProvider.class;\n\tfinal Class\u003c? extends SecureRandom\u003e myRandomClass = SecureRandom.class;\n\tfinal Properties props = new Properties();\n\tprops.setProperty(Pbkdf2Encoder.KEY_SECRET, \"secret\");\n\tprops.setProperty(Pbkdf2Encoder.KEY_HASH_LENGTH, String.valueOf(1024));\n\tprops.setProperty(Pbkdf2Encoder.KEY_SALT_LENGTH, String.valueOf(128));\n\tprops.setProperty(Pbkdf2Encoder.KEY_ITERATIONS, String.valueOf(200000));\n\tprops.setProperty(Pbkdf2Encoder.KEY_ALGORITHM, Pbkdf2Encoder.ALGORITHM_PBKDF2_HMAC_SHA1);\n\tprops.setProperty(Pbkdf2Encoder.KEY_PROVIDER_CLASS, providerClass.getName());\n\tprops.setProperty(Pbkdf2Encoder.KEY_RANDOM, myRandomClass.getName());\n\tprops.setProperty(Pbkdf2Encoder.KEY_PREFIX, \"{pbkdf2}\");\n\t// Setup encoder\n\tfinal Pbkdf2Encoder encoder = new Pbkdf2Encoder();\n\tencoder.configure(props, null);\n\t// Hash and compare\n\tfinal String encoded1 = encoder.encode(\"PASSWORD\");\n\tSystem.out.println(\"Hashed1: \" + encoded1);\n\tfinal String encoded2 = encoder.encode(\"PASSWORD\");\n\tSystem.out.println(\"Hashed2: \" + encoded2);\n\tSystem.out.println(\"Matches1: \" + encoder.matches(\"PASSWORD\", encoded1));\n\tSystem.out.println(\"Matches2: \" + encoder.matches(\"PASSWORD\", encoded2));\n```\nNote that each encoding will be different, but both will match the same input value.\n\n#### Declarative password encoding via Hibernate UserType annotations\nIn a JPA/Hibernate environment, password encoding can be declared on POJO's using annotations. This allows for hashing of the field value as it is persisted to the database. The value retrieved from the database will remain hashed. Matching of the password will require a reference to the encoder, which can be retrieved via the `PasswordEncoderStore` after setting the name in the storeExportKey property. Except for 'pswdEncoder', the parameters are all optional overrides of default settings.\n\nHere is an example for Argon2id:\n```java\n\t@Type(type = \"org.antfarmer.ejce.password.EncodedPasswordType\", parameters = {\n\t\t@Parameter(name = \"pswdEncoder\", value = \"org.antfarmer.ejce.password.encoder.Argon2JvmEncoder\"),\n\t\t@Parameter(name = \"type\", value = \"id\"),\n\t\t@Parameter(name = \"hashLen\", value = \"64\"),\t// Bytes\n\t\t@Parameter(name = \"saltLen\", value = \"32\"),\t// Bytes\n\t\t@Parameter(name = \"iterations\", value = \"100\"),\n\t\t@Parameter(name = \"parallelism\", value = \"4\"),\t// Threads\n\t\t@Parameter(name = \"memSize\", value = \"65536\"),\t// KB\n\t\t@Parameter(name = \"storeExportKey\", value = \"com.myapp.pswd.user\")\n\t})\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n```\n\nHere is an example for referencing a pre-configured password encoder in the `PasswordEncoderStore`:\n```java\n\t... // in some bootstrap class\n\tPasswordEncoderStore.add(\"com.myapp.pswd.user\", mySecretEncryptor);\n\t... // in POJO\n\t@Type(type = \"org.antfarmer.ejce.password.EncodedPasswordType\", parameters = {\n\t\t@Parameter(name = \"storeKey\", value = \"com.myapp.pswd.user\")\n\t})\n\tpublic String getPassword() {\n\t\treturn password;\n\t}\n```\n\nIn your security logic, credential verification can be checked via encoder reference:\n```java\n\tpublic boolean matches(CharSequence rawPassword, String encodedPassword) {\n\t\t// rawPassword comes from user login form\n\t\t// encodedPassword comes from user.getPassword()\n\t\treturn PasswordEncoderStore.get(\"com.myapp.pswd.user\").matches(rawPassword, encodedPassword);\n\t}\n```\nMore possible parameter keys and values can found in `ConfigurerUtil` and the appropriate `PasswordEncoder` classes.\n\n#### Password encoding via Hibernate UserType using XML configuration\nIn a JPA/Hibernate environment, password encoding can also be configured via mapping XML. This allows for hashing of the field value as it is persisted to the database. The value retrieved from the database will remain hashed. Matching of the password will require a reference to the encoder, which can be retrieved via the `PasswordEncoderStore` after setting the name in the storeExportKey property. Except for 'pswdEncoder', the parameters are all optional overrides of default settings.\n\nHere is an example for the BCrypt algorithm:\n```xml\n\u003chibernate-mapping\u003e\n\t\u003ctypedef name=\"encodedPassword\" class=\"org.antfarmer.ejce.password.EncodedPasswordType\"\u003e\n\t\t\u003cparam name=\"pswdEncoder\"\u003eorg.antfarmer.ejce.password.encoder.bc.BcBcryptEncoder\u003c/param\u003e\n\t\t\u003cparam name=\"version\"\u003e2b\u003c/param\u003e\n\t\t\u003cparam name=\"strength\"\u003e7\u003c/param\u003e\n\t\t\u003cparam name=\"storeExportKey\"\u003ecom.myapp.pswd.user\u003c/param\u003e\n\t\u003c/typedef\u003e\n\t...\n\t\u003cclass name=\"...\"\u003e\n\t\t...\n\t\t\u003cproperty name=\"password\" type=\"encodedPassword\"/\u003e\n\t\t...\n\t\u003c/class\u003e\n\u003c/hibernate-mapping\u003e\n```\nMore possible parameter keys and values can found in `ConfigurerUtil` and the appropriate `PasswordEncoder` classes.\n\n\n## API Documentation\nPlease have a look at the [API documentation](https://antfarmer.github.io/easyjce/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantfarmer%2Feasyjce","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fantfarmer%2Feasyjce","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantfarmer%2Feasyjce/lists"}