Repository: OmniOneID/did-crypto-sdk-server Branch: develop Commit: 23c39046f5e4 Files: 62 Total size: 222.5 KB Directory structure: gitextract_6r4g9vmi/ ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yaml │ │ └── feature_request.yaml │ ├── pull_request_template.yml │ └── workflows/ │ ├── auto_assign.yml │ ├── build.yml │ ├── cla.yml │ └── crypto_sdk_ci.yml ├── .gitignore ├── CHANGELOG.md ├── CLA.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAINERS.md ├── README.md ├── README_ko.md ├── RELEASE-PROCESS.md ├── SECURITY.md ├── dependencies-license.md ├── docs/ │ └── api/ │ ├── CRYPTO_SDK-SERVER_API.md │ ├── CRYPTO_SDK-SERVER_API_ko.md │ └── CryptoSDKError.md ├── signatures/ │ └── version1/ │ └── cla.json └── source/ ├── did-crypto-sdk-server/ │ ├── .gitignore │ ├── README.md │ ├── README_ko.md │ ├── build.gradle │ ├── gradle/ │ │ └── wrapper/ │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src/ │ └── main/ │ └── java/ │ └── org/ │ └── omnione/ │ └── did/ │ └── crypto/ │ ├── constant/ │ │ └── CryptoConstant.java │ ├── ec/ │ │ └── CompactSign.java │ ├── encoding/ │ │ └── Base58.java │ ├── engines/ │ │ ├── AesEngine.java │ │ └── CipherInfo.java │ ├── enums/ │ │ ├── DidKeyType.java │ │ ├── DigestType.java │ │ ├── EccCurveType.java │ │ ├── EncryptionMode.java │ │ ├── EncryptionType.java │ │ ├── MultiBaseType.java │ │ ├── SymmetricCipherType.java │ │ ├── SymmetricKeySize.java │ │ └── SymmetricPaddingType.java │ ├── exception/ │ │ ├── CryptoErrorCode.java │ │ ├── CryptoErrorCodeInterface.java │ │ └── CryptoException.java │ ├── generator/ │ │ ├── EcKeyPairGenerator.java │ │ ├── GenerateSecureRandom.java │ │ └── RsaKeyPairGenerator.java │ ├── keypair/ │ │ ├── EcKeyPair.java │ │ ├── KeyPairInterface.java │ │ └── RsaKeyPair.java │ ├── signature/ │ │ ├── EccSignatureProvider.java │ │ └── SignatureProvider.java │ └── util/ │ ├── CryptoUtils.java │ ├── DigestUtils.java │ ├── MultiBaseUtils.java │ └── SignatureUtils.java └── release/ └── did-crypto-sdk-server-2.0.0.jar ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yaml ================================================ name: Bug Report description: File a bug report. title: "[Bug]: " labels: ["bug", "triage"] assignees: [""] body: - type: markdown attributes: value: | Thanks for taking the time to fill out this bug report! - type: textarea id: what-happened attributes: label: What happened? description: Also tell us, what did you expect to happen? placeholder: Tell us what you see! validations: required: true - type: input id: version attributes: label: Version description: What version of our software are you running? validations: required: true - type: textarea id: logs attributes: label: Relevant log output description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. render: shell - type: checkboxes id: terms attributes: label: Code of Conduct description: By submitting this issue, you agree to follow our [Code of Conduct](../blob/main/CODE_OF_CONDUCT.md). options: - label: I agree to follow this project's Code of Conduct required: true ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.yaml ================================================ name: Feature request description: Suggest an idea for this project title: "[Feature]: " labels: ["enhancement"] body: - type: markdown attributes: value: | Thanks for taking the time to fill out this feature request! - type: textarea id: feature attributes: label: Feature Description description: Please provide a detailed description of the feature. placeholder: Describe the feature you are requesting. validations: required: true - type: textarea id: purpose attributes: label: Purpose description: What is the main purpose of this feature? Why is it needed? placeholder: Explain the purpose of the feature. validations: required: true - type: textarea id: background attributes: label: Background description: Provide any relevant context or background information for this feature. placeholder: Provide background information. validations: required: false - type: textarea id: expected_outcome attributes: label: Expected Outcome description: What are the expected results of implementing this feature? placeholder: Explain the expected results or impact. validations: required: true - type: checkboxes id: terms attributes: label: Code of Conduct description: By submitting this issue, you agree to follow our [Code of Conduct](../blob/main/CODE_OF_CONDUCT.md). options: - label: I agree to follow this project's Code of Conduct required: true ================================================ FILE: .github/pull_request_template.yml ================================================ ## Description ## Related Issue (Optional) - Issue # (e.g., #123) ## Changes - Change 1 - Change 2 ## Screenshots (Optional) ## Additional Comments (Optional) ================================================ FILE: .github/workflows/auto_assign.yml ================================================ name: PR assignment on: pull_request_target: types: [opened, edited, synchronize, reopened, ready_for_review] permissions: contents: read issues: write pull-requests: write jobs: auto-assign: runs-on: ubuntu-latest steps: - name: Request Reviewers uses: actions/github-script@v6 with: script: | const author = context.payload.pull_request.user.login; let reviewers = ['crham','ejlee8796','sjyeo98']; if (reviewers.includes(author)) { if(reviewers.length === 1) reviewers = reviewers.map(reviewer => reviewer === author ? 'mikyung-lee' : reviewer); else { reviewers = reviewers.filter(reviewer => reviewer !== author); } } await github.rest.pulls.requestReviewers({ owner: context.repo.owner, repo: context.repo.repo, pull_number: context.payload.pull_request.number, reviewers: reviewers }); - name: Request Assignees uses: actions/github-script@v6 with: script: | const assignees = ['crham', 'mikyung-lee']; // assignees await github.rest.issues.addAssignees({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, assignees: assignees }); ================================================ FILE: .github/workflows/build.yml ================================================ name: Build and Upload JAR to GitHub Releases on: pull_request: branches: - main types: [closed] jobs: build: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/QA-') runs-on: ubuntu-latest permissions: contents: write pull-requests: write repository-projects: write defaults: run: working-directory: source/did-crypto-sdk-server steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up JDK 21 uses: actions/setup-java@v4 with: java-version: '21' distribution: 'temurin' - name: Build JAR run: | gradle build echo "JAR file generated at:" find ./build/libs -name "*.jar" - name: Set release title id: set_release_title run: | release_tag=${GITHUB_HEAD_REF#release/QA-} echo "Release tag: $release_tag" echo "::set-output name=release_tag::$release_tag" - name: Get commit messages id: get_commit_messages run: | commits=$(git log ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} --pretty=format:"* %s") echo "$commits" > commit_messages.txt echo "::set-output name=commits::$commits" - name: Find JAR file id: find_jar run: | jar_path=$(find ./build/libs -name "*.jar" | head -n 1) echo "JAR path found: $jar_path" echo "::set-output name=jar_path::$jar_path" - name: Calculate SHA-256 id: calculate_sha run: | sha256=$(sha256sum ${{ env.jar_path }} | awk '{ print $1 }') echo "SHA-256: $sha256" echo "::set-output name=jar_sha256::$sha256" - name: Create GitHub Release id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ steps.set_release_title.outputs.release_tag }} release_name: ${{ steps.set_release_title.outputs.release_tag }} body: | ## Changes: ${{ steps.get_commit_messages.outputs.commits }} ## Checksum: SHA-256: ${{ steps.calculate_sha.outputs.jar_sha256 }} - name: Upload JAR uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: source/did-crypto-sdk-server/${{ steps.find_jar.outputs.jar_path }} asset_name: did-crypto-sdk-server-${{ steps.set_release_title.outputs.release_tag }}.jar asset_content_type: application/java-archive ================================================ FILE: .github/workflows/cla.yml ================================================ name: "CLA Assistant" on: issue_comment: types: [created] pull_request_target: types: [opened,closed,synchronize] # explicitly configure permissions, in case your GITHUB_TOKEN workflow permissions are set to read-only in repository settings permissions: actions: write contents: write # this can be 'read' if the signatures are in remote repository pull-requests: write statuses: write jobs: CLAAssistant: runs-on: ubuntu-latest steps: - name: "CLA Assistant" if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' uses: contributor-assistant/github-action@v2.6.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # the below token should have repo scope and must be manually added by you in the repository's secret # This token is required only if you have configured to store the signatures in a remote repository/organization # PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} with: path-to-signatures: 'signatures/version1/cla.json' path-to-document: 'https://github.com/OmniOneID/did-crypto-sdk-server/blob/main/CLA.md' # e.g. a CLA document # branch should not be protected branch: 'main' allowlist: user1,bot* # the followings are the optional inputs - If the optional inputs are not given, then default values will be taken #remote-organization-name: enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository) #remote-repository-name: enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository) #create-file-commit-message: 'For example: Creating file for storing CLA Signatures' #signed-commit-message: 'For example: $contributorName has signed the CLA in $owner/$repo#$pullRequestNo' #custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign' #custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA' #custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.' #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true) #use-dco-flag: true - If you are using DCO instead of CLA ================================================ FILE: .github/workflows/crypto_sdk_ci.yml ================================================ name: Java CI with Gradle on: push: branches: - "release/**" - "main" - "develop" jobs: build: runs-on: ubuntu-latest defaults: run: working-directory: source/did-crypto-sdk-server permissions: contents: read steps: - uses: actions/checkout@v4 - name: Set up JDK 21 uses: actions/setup-java@v4 with: java-version: '21' distribution: 'temurin' - name: Build with Gradle run: gradle clean build - name: Upload Build Artifact uses: actions/upload-artifact@v4 with: name: build-${{ github.sha }} path: | source/did-crypto-sdk-server/build/libs/*.jar ================================================ FILE: .gitignore ================================================ HELP.md .gradle build/ !gradle/wrapper/gradle-wrapper.jar !**/src/main/**/build/ !**/src/test/**/build/ ### STS ### .apt_generated .classpath .factorypath .project .settings .springBeans .sts4-cache bin/ !**/src/main/**/bin/ !**/src/test/**/bin/ ### IntelliJ IDEA ### .idea *.iws *.iml *.ipr out/ !**/src/main/**/out/ !**/src/test/**/out/ ### NetBeans ### /nbproject/private/ /nbbuild/ /dist/ /nbdist/ /.nb-gradle/ ### VS Code ### .vscode/ ### macOS ### .DS_Store ================================================ FILE: CHANGELOG.md ================================================ # Changelog ## v2.0.0 (2025-05-26) ### 🚀 New Features - Java Compile Version Upgrade - Updated Java compile version from 17 to 21 ## v1.0.0 (2024-10-18) ### 🚀 New Features - Supports key generation for ECC and RSA, along with encryption and decryption capabilities - Support for SHA-256, SHA-384, and SHA-512 hash functions. - Supports MultiBase encoding and decoding functionality. - Provides functionality for signature generation and verification. ================================================ FILE: CLA.md ================================================ # Individual Software Grant and Contributor License Agreement ## Based on the Apache Software Foundation Software Grant and Individual Contributor License Agreement ### http://www.apache.org/licenses/ Thank you for your interest in the OpenDID project (the “Project”). In order to clarify the intellectual property license granted with Contributions (defined below) from any person or entity, the Project must have a Contributor License Agreement (“CLA”) on file that has been signed by each Contributor, indicating agreement to the license terms below. This license is for your protection as a Contributor as well as the protection of the Project and its users; it does not change your rights to use your own Contributions for any other purpose. You accept and agree to the following terms and conditions for Your present and future Contributions submitted to the Project. In return, the Project shall not use Your Contributions in a way that is contrary to the public benefit or inconsistent with its nonprofit status and bylaws in effect at the time of the Contribution. Except for the license granted herein to the Project and recipients of software distributed by the Project, You reserve all right, title, and interest in and to Your Contributions. **1. Definitions.** This document is a CLA (Contributor License Agreement) that must be signed by all Contributors to the Project. **“You”** or **“Your”** shall mean the copyright owner or legal entity authorized by the copyright owner that is making this CLA with the Project. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, “control” means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. **“Contribution”** shall mean the code, documentation or other original works of authorship expressly identified in Schedule A, as well as any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to the Project for inclusion in, or documentation of, any of the products owned or managed by the Project (the **“Work”**). For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication sent to the Project or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Project for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as “Not a Contribution.” **2. Grant of Copyright License.** Subject to the terms and conditions of this CLA, You hereby grant to the Project and to recipients of software distributed by the Project a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. For the avoidance of doubt, by agreeing to this CLA, You confirm that the Project and recipients of software distributed by the Project are free to use the code, documentation, or other original works of authorship that You submit as part of Your Contributions. **3. Grant of Patent License.** Subject to the terms and conditions of this CLA, You hereby grant to the Project and to recipients of software distributed by the Project a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. Should any entity initiate patent litigation against you or any other entity (imcluding through a cross-claim or counterclaim in a lawsuit), alleging that your Contribution or the Work to which you have contributed constitutes direct or contributory patent infrigement, any patent licenses granted to that entity for the Contribution or Work shall be terminated as of the date such litigation is filed. **4. Representations with Respect to the License and Contributions.** You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to the Project, or that your employer has executed a separate Corporate CLA with the Project. **5. Additional Representations with Respect to Contributions.** You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. **6. Disclaimers.** You have no additional obligations, such as making further code support, after making a Contribution, and any support for Your Contribution is at Your discretion. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASE, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. Also, You shall retain the rights to Your Contribution and may use it for other projects or purposes. **7. Non-Original Creations.** Should You wish to submit work that is not Your original creation, You may submit it to the Project separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as “Submitted on behalf of a third-party: [named here].” Additionally, if submitting non-original works, You must cleary specify the original author's license and submit it as a separate file. If You violate this obligation by submitting a third party's work without proper authorization, resulting in copyright infrigement, You shall be solely responsible for any legal liabilities arising from such infrigement. **8. Agreements.** You agree to notify the Project of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. "To sign this CLA, please follow the automated procedure on GitHub or download the PDF, sign it, and submit it to technology@omnione.net." ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported at [technology@omnione.net](mailto:technology@omnione.net). to the community leaders responsible for enforcement. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations]. [homepage]: https://www.contributor-covenant.org [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations ================================================ FILE: CONTRIBUTING.md ================================================ # Contribution Guidelines We appreciate your contributions! We want to make contributing to this project as easy and transparent as possible, whether it's: - Reporting a bug - Discussing the current state of the code - Submitting a fix - Proposing new features ## Contribution Process Thank you for contributing to the project! This guide explains how to contribute to the project, the code style rules, and the review criteria. Please familiarize yourself with the following content before making any contributions. 1. **Creating an Issue** - Before starting any work, create an issue related to the task you wish to work on. All work, including bug fixes, feature improvements, and new proposals, should be initiated after the issue is registered. - When creating an issue, use the provided issue template and fill in accurate information. 2. **Issue Assignment** - Once the issue is created, the administrator will review and may assign the issue to an external contributor. - Before being assigned, make sure that the same task is not already in progress. 3. **Fork and Branch Creation** - Refer to [Pull Request Guidelines](#pull-request-guidelines) 4. **Writing Code** - Ensure that the code strictly follows the project's [Coding Style](#coding-style) guidelines. - Submit the PR after confirming that all tests pass successfully. 5. **Creating a Pull Request (PR)** - Commit your work and create a PR. - In the PR description, provide detailed information about the changes and link the related issue number to connect it to the issue. - Write concise and clear commit messages. - Refer to [Commit Message Guideline](#commit-message-guidelines) 6. **Code Review** - Once the PR is created, the administrator will review the code. Update the PR by incorporating the reviewer’s feedback. - Once the review is complete, the administrator will merge the PR. ## Detailed Contribution Guide via GitHub Please refer to [Detailed Contribution Guide via GitHub](https://github.com/OmniOneID/did-doc-architecture/blob/main/how_to_contribute_to_open_did.md) for detailed instructions on how to contribute to the project. This guide includes command examples and screenshots to help you better understand the process. ## Code Review Standards We conduct code reviews based on the following standards to ensure that your contribution maintains consistency with the project and upholds quality: 1. **Code Quality** - Write code that is easy to read and maintain. - Avoid overly complex logic, and if possible, suggest better solutions. - Minimize duplicated code and check if the code can be refactored into reusable modules. 2. **Feature Verification** - Test the new feature or bug fix to ensure it works as intended. - All tests must pass before submitting the PR. - Include any additional necessary tests in the PR. 3. **Code Style Compliance** - Ensure that your code follows the project's [Coding Style](#coding-style). - Feedback will be given if there are formatting issues or violations of naming conventions. 4. **Commit Messages** - Ensure that commit messages clearly describe the changes made. - Avoid including too many modifications in a single commit. If possible, divide changes into smaller commits. 5. **Documentation** - If new features, APIs, or configuration changes are introduced, make sure to update or add relevant documentation. - Write appropriate comments in the code, especially for explaining complex logic. ## Code of Conduct We are committed to fostering a contribution environment where everyone is treated with respect. Please make sure to read and follow the [Code of Conduct](CODE_OF_CONDUCT.md) before starting your contribution. ## Issue Reporting Guidelines We use GitHub Issues to track and manage bugs. If you encounter a bug, please open a new issue on GitHub. When reporting an issue, please use the provided issue template to clearly describe the problem. This helps us resolve the issue more quickly. ### Writing a Good Bug Report A good bug report includes the following: - A quick summary or background of the issue. - Steps to reproduce the bug (be specific and detailed). - Expected vs. actual results. - Any additional context or information that could help us diagnose the issue. ## Pull Request Guidelines 1. **Fork** from the `develop` branch of the remote repository. 2. **Develop the feature**, and ensure the code has been properly tested. 3. If necessary, update the **documentation** to reflect the changes. 4. Verify that all tests pass and that the code adheres to our coding style and linting rules. 5. Once the work is complete, submit a **pull request** to the `develop` branch. 6. When creating the pull request, assign an appropriate **reviewer** to review the code changes. It is recommended to choose someone familiar with the codebase, considering their availability for providing feedback. 7. Also, assign **assignees** to clarify responsibility for the task. Assign **all maintainers of the repository** as assignees to ensure accountability and a smooth review process. > **Note**: Assignees are responsible for ensuring the pull request is reviewed and merged appropriately. Assigning all maintainers as assignees is a crucial step to ensure they are aware of the changes and can respond quickly. ## Coding Style Our coding style is based on the [OpenDID Coding Style](https://github.com/OmniOneID/did-doc-architecture/blob/main/docs/rules/coding_style.md). Adhering to these guidelines ensures that the code is clean, readable, and maintainable. ## Document Creation and Editing Guide Our document creation process follows the [OpenDID Document Guide](https://github.com/OmniOneID/did-doc-architecture/blob/main/docs/guide/docs/write_document_guide.md). Most of the design documents we create use the Markdown (*.md) format, ensuring consistency and ease of collaboration. ## Commit Message Guidelines Our commit messages follow the [OpenDID Commit Rule](https://github.com/OmniOneID/did-doc-architecture/blob/main/docs/rules/git_code_commit_rule.md). Well-structured commit messages help others understand the intent behind your changes and make it easier to navigate the code history. ## Signing the CLA Before we can accept your pull request, you must submit a CLA. This only needs to be done once. Complete your CLA here: [Contributor License Agreement](CLA.md) ## License [Apache 2.0](LICENSE) ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2024 OmniOne. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: MAINTAINERS.md ================================================ # Maintainers ## Overview This file lists the maintainers for this project. Maintainers are responsible for reviewing and merging pull requests, ensuring code quality, and managing releases. If you have any questions or require support, please reach out to the maintainers listed below. ## Maintainers | Name | GitHub | email | |---------------------------|------------------|--------------------------------------------| | Chorom Ham | crham | crham@raoncorp.com | | Eunjeong Lee | ejlee8796 | ejlee8796@raoncorp.com | | Seungjae Yeo | sjyeo98 | sjyeo@raoncorp.com | ================================================ FILE: README.md ================================================ # Crypto Server SDK Welcome to the Crypto Server SDK Repository.
This repository provides an SDK for key generation, encryption/decryption, and other related functions. ## Folder Structure ``` did-crypto-sdk-server ├── CHANGELOG.md ├── CLA.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── dependencies-license.md ├── MAINTAINERS.md ├── README.md ├── README_ko.md ├── RELEASE-PROCESS.md ├── SECURITY.md ├── docs │ └── api │ ├── CRYPTO_SDK_SERVER_API.md │ ├── CRYPTO_SDK_SERVER_API_ko.md │ └── CryptoSDKError.md └── source ├── did-crypto-sdk-server │ ├── README.md │ ├── README_ko.md │ ├── build.gradle │ ├── gradle │ │   └── wrapper │ ├── .gitignore │ ├── build │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src └── release └── did-crypto-sdk-server-2.0.0.jar ``` | Name | Description | | ----------------------- | ----------------------------------------------- | | source | SDK source code project | | docs | Documentation | | ┖ api | API guide documentation | | README.md | Overview and description of the project | | CLA.md | Contributor License Agreement | | CHANGELOG.md | Version-specific changes in the project | | CODE_OF_CONDUCT.md | Code of conduct for contributors | | CONTRIBUTING.md | Contribution guidelines and procedures | | LICENSE | Apache 2.0 | | dependencies-license.md | Licenses for the project’s dependency libraries | | MAINTAINERS.md | General guidelines for maintaining | | RELEASE-PROCESS.md | Release process | | SECURITY.md | Security policies and vulnerability reporting | ## Build Method : Create a JAR file based on the build.gradle file of this SDK project. 1. Open the `build.gradle` file of your project and add a task from the configuration file as shown below. ```groovy plugins { id 'java' } group = 'org.omnione.did' java { sourceCompatibility = '21' } jar { archiveBaseName.set('did-crypto-sdk-server') archiveVersion.set('2.0.0') archiveClassifier.set('') } repositories { mavenCentral() } dependencies { implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' } ``` 2. Open the `Gradle` tab in IDE and run the project's `Task > Build > Clean and Build` task, or type `./gradlew clean & build` in a terminal. 3. Once the execution is complete, the `did-crypto-sdk-server-2.0.0.jar` file will be generated in the `{projetPath}/build/libs/` folder.
## Libraries Libraries can be found in the [Releases](https://github.com/OmniOneID/did-crypto-sdk-server/releases). ## Crypto SDK 1. Copy the did-crypto-sdk-server-2.0.0.jar file to the libs of the server project. 2. Add the following dependencies to the server project's build.gradle. ```groovy implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' implementation files('libs/did-crypto-sdk-server-2.0.0.jar') ``` 3. Sync `Gradle` to ensure the dependencies are properly added. ## API Reference API Reference can be found [here](docs/CRYPTO_SDK-SERVER_API.md) ## Change Log The Change Log provides a detailed record of version-specific changes and updates. You can find it here: - [Change Log](./CHANGELOG.md) ## OpenDID Demonstration Videos
To watch our demonstration videos of the OpenDID system in action, please visit our [Demo Repository](https://github.com/OmniOneID/did-demo-server).
These videos showcase key features including user registration, VC issuance, and VP submission processes. ## Contributing Please read [CONTRIBUTING.md](CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for details on our code of conduct, and the process for submitting pull requests to us. ## License [Apache 2.0](LICENSE) ================================================ FILE: README_ko.md ================================================ # Crypto Server SDK Crypto Server SDK Repository에 오신 것을 환영합니다.
이 Repository는 키 생성, 암/복호화 등을 개발하기 위한 SDK를 제공합니다. ## 폴더 구조 ``` did-crypto-sdk-server ├── CHANGELOG.md ├── CLA.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── dependencies-license.md ├── MAINTAINERS.md ├── README.md ├── README_ko.md ├── RELEASE-PROCESS.md ├── SECURITY.md ├── docs │ └── api │ ├── CRYPTO_SDK_SERVER_API.md │ ├── CRYPTO_SDK_SERVER_API_ko.md │ └── CryptoSDKError.md └── source ├── did-crypto-sdk-server │ ├── README.md │ ├── README_ko.md │ ├── build.gradle │ ├── gradle │ │   └── wrapper │ ├── .gitignore │ ├── build │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src └── release └── did-crypto-sdk-server-2.0.0.jar ``` | 이름 | 역할 | | ------- | ------------------------------------ | | source | SDK 소스코드 프로젝트 | | docs | 문서 | | ┖ api | API 가이드 문서 | | README.md | 프로젝트의 전체적인 개요 설명 | | CLA.md | Contributor License Agreement | | CHANGELOG.md| 프로젝트 버전별 변경사항 | | CODE_OF_CONDUCT.md| 기여자의 행동강령 | | CONTRIBUTING.md| 기여 절차 및 방법 | | LICENSE | Apache 2.0 | | dependencies-license.md| 프로젝트 의존성 라이브러리에 대한 라이선스 | | MAINTAINERS.md | 유지관리 가이드 | | RELEASE-PROCESS.md | 릴리즈 절차 | | SECURITY.md| 보안취약점 보고 및 보안정책 | ## 빌드 방법 : 본 SDK 프로젝트의 build.gradle 파일을 기반으로 JAR 파일을 생성한다. 1. 프로젝트의 `build.gradle` 파일을 열고 아래와 같은 구성파일의 태스크를 추가한다. ```groovy plugins { id 'java' } group = 'org.omnione.did' java { sourceCompatibility = '21' } jar { archiveBaseName.set('did-crypto-sdk-server') archiveVersion.set('2.0.0') archiveClassifier.set('') } repositories { mavenCentral() } dependencies { implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' } ``` 2. IDE에서 `Gradle` 창을 열고, 프로젝트의 `Tasks > build > clean & build` 태스크를 실행 또는 `./gradlew clean & build` 를 터미널 창에 입력한다. 3. 실행이 완료되면 `{projetPath}/build/libs/` 폴더에 `did-crypto-sdk-server-2.0.0.jar` 파일이 생성된다.
## 라이브러리 라이브러리는 [Releases](https://github.com/OmniOneID/did-crypto-sdk-server/releases) 에서 찾을 수 있습니다. ## Core SDK 1. 서버 프로젝트의 libs에 did-crypto-sdk-server-2.0.0.jar 파일을 복사한다. 2. 서버 프로젝트의 build gradle에 아래 의존성을 추가한다. ```groovy implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' implementation files('libs/did-crypto-sdk-server-2.0.0.jar') ``` 3. `Gradle`을 동기화하여 의존성이 제대로 추가되었는지 확인한다. ## API 참조 API 참조는 [여기](docs/CRYPTO_SDK-SERVER_API_ko.md)에서 확인할 수 있습니다. ## Change Log Change Log에는 버전별 변경 사항과 업데이트가 자세히 기록되어 있습니다. 다음에서 확인할 수 있습니다: - [Change Log](./CHANGELOG.md) ## 데모 영상
OpenDID 시스템의 실제 동작을 보여주는 데모 영상은 [Demo Repository](https://github.com/OmniOneID/did-demo-server)에서 확인하실 수 있습니다.
사용자 등록, VC 발급, VP 제출 등 주요 기능들을 영상으로 확인하실 수 있습니다. ## 기여 Contributing 및 pull request 제출 절차에 대한 자세한 내용은 [CONTRIBUTING.md](CONTRIBUTING.md)와 [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) 를 참조하세요. ## 라이선스 [Apache 2.0](LICENSE) ================================================ FILE: RELEASE-PROCESS.md ================================================ # Release Process This document describes the Release Process for QA validation and deployment of feature additions and modifications for each repository. It covers version management and QA validation procedures for each module, as well as the process for managing the integrated Release of all modules. ## 1. Versioning The project follows a versioning rule in the format "X.Y.Z" where: - X (Major): Significant changes that are not backward compatible - Y (Minor): New features that are backward compatible - Z (Patch): Bug fixes or minor improvements that are backward compatible > When the Major version is updated, both Minor and Patch are reset to 0. >
> When the Minor version is updated, the Patch is reset to 0. The integrated module version follows a four-digit format "W.X.Y.Z" assigned after QA approval. - W.X: Official product number - Y: Release - Z: Bug fix ## 2. Release Procedure for Each Repository Each module (repository) is managed independently, following these steps: 1. **Change Log Review** Review the [CHANGE LOG](CHANGELOG.md) for each module to ensure all changes are recorded. 2. **Create a Release Branch** If there are changes or modifications, create a branch "release/QA-VX.Y.Z" for QA validation. - Example: If there are bug fixes or minor improvements for V1.0.0, create a branch "release/QA-V1.0.1". For modules without changes, use the existing version (V1.0.0) and the already distributed JAR or library. 3. **QA Validation** - Perform QA validation on the Release branch, addressing any issues identified during the process. - Approve the Release once QA validation is complete. 4. **Merge into Main and Develop Branches** - Merge the validated Release branch (release/QA-VX.Y.Z) into both `main` and `develop` branches. 5. **Create a Release for Each Repository** - When the validated branch is merged into `main`, trigger the [CI/CD pipeline](https://github.com/OmniOneID/did-release/blob/main/docs/CI_CD_PIPELINE.md) using GitHub Actions to create the Release and perform version tagging. The generated [Release](https://github.com/OmniOneID/did-crypto-sdk-server/releases) includes the following: - Version name - Summary of the changelog - Source code archive - Distributed files - Delete the release/QA-VX.Y.Z branch after the release. ## 3. Integrated Release Management (did-release Repository) After QA approval, manage the complete version control of all modules in a separate repository called [did-release](https://github.com/OmniOneID/did-release/). 1. **Managing QA Request Branches** - Create a directory for the QA request version (format: W.X.Y.Z, e.g., V1.0.1.0). The directory name should be /release-VW.X.Y.Z (e.g., /release-V1.0.1.0). - Gather the version names of the branches created for QA validation (release/QA-VX.Y.Z) and document version information and modifications in a table within the directory. Name the file 'QA-PLAN-VW.X.Y.Z.md' and register it in the issue menu of the `did-release` repository. - Include versions of unchanged modules as well. 2. **Individual Releases After QA Approval** - Once all modules have passed QA validation, and their respective `release/QA-VX.Y.Z` branches are merged into `main` and `develop`, create releases for each repository. 3. **Publishing the Integrated Release** - After all modules are approved and released, manage the integrated Release in the `did-release` repository. - Retrieve the latest version tags for each module and post them in the Release menu of the `did-release`. - Document the release information in a file named release-VW.X.Y.Z.md within the previously created directory. - Example: ## Release Note V1.0.1.0 | Repository | Version | Changelog | Release | | ------------------ | --------------- | --------------------------- | --------------------------- | | did-crypto-sdk-server | V1.0.1 | [Changelog](https://github.com/OmniOneID/did-crypto-sdk-server/blob/main/CHANGELOG.md) | | .. | .. | .. |
## 4. Automating Integrated Release Script Use GitHub Actions or Shell scripts to automate the following tasks: - Retrieve the release tag information for each module and publish the integrated Release. - Once all module releases are completed, gather the latest Release information for each module and publish the final version in the `did-release` repository to manage the overall project release. - The integrated release version follows the "W.X.Y.Z" format, based on the most significant changes. This process enables efficient management of individual module versions and the overall integrated project release. ================================================ FILE: SECURITY.md ================================================ # Security Policy ## Supported Versions In this project, the following versions have undergone security vulnerability assessments: | Version | Supported | | ------- | ------------------ | | 1.0.0 | ✅ | ## Reporting a Vulnerability If you discover a new security vulnerability, please report it via [technology@omnione.net](mailto:technology@omnione.net). ## Sensitive Information Protection Please ensure that sensitive information, such as API keys, passwords, and personal data, is never included in the code or documentation. Such information should be managed outside the code, preferably using environment variables. ## Security Policy Configuration - Vulnerability Management: If a vulnerability is discovered, follow the security reporting procedures and collaborate to apply security patches as quickly as possible. - Code Review: Any changes related to security must always go through the review process, and multiple contributors should be involved in the review to ensure thorough checks. ================================================ FILE: dependencies-license.md ================================================ # License Information ### This project uses the following third-party libraries, each under its own license:
**Bouncy Castle Provider: Bouncy Castle Licence** `org.bouncycastle:bcprov-jdk18on:1.78.1` (https://github.com/bcgit/bc-java/blob/main/LICENSE.html) ================================================ FILE: docs/api/CRYPTO_SDK-SERVER_API.md ================================================ --- puppeteer: pdf: format: A4 displayHeaderFooter: true landscape: false scale: 0.8 margin: top: 1.2cm right: 1cm bottom: 1cm left: 1cm image: quality: 100 fullPage: false --- Crypto SDK Server API == - title: Crypto SDK Server API - author: Seung-Jae Yeo - date: 2024-08-30 - version: v1.0.0 | Version | Date | Changes | | ------- | ---------- | ---------------------- | | v1.0.0 | 2024-08-30 | Initial creation |
# Table of Contents - [1. APIs](#1-apis) - [1.1 CryptoUtils](#11-cryptoutils) - [1.1.1 generateKeyPair](#111-generatekeypair) - [1.1.2 compressPublicKey](#112-compresspublickey) - [1.1.3 unCompressPublicKey](#113-uncompresspublickey) - [1.1.4 generateNonce](#114-generatenonce) - [1.1.5 generateSalt](#115-generatesalt) - [1.1.6 generateSharedSecret](#116-generatesharedsecret) - [1.1.7 pbkdf2](#117-pbkdf2) - [1.1.8 encrypt](#118-encrypt) - [1.1.9 decrypt](#119-decrypt) - [1.2 DigestUtils](#12-digestutils) - [1.2.1 getDigest](#121-getdigest) - [1.3 MultiBaseUtils](#13-multibaseutils) - [1.3.1 encode](#131-encode) - [1.3.2 decode](#132-decode) - [1.4 SignatureUtils](#14-signatureutils) - [1.4.1 generateCompactSignature](#141-generatecompactsignature) - [1.4.2 generateEccSignatureFromHashedData](#142-generateeccsignaturefromhasheddata) - [1.4.3 convertToCompactSignature](#143-converttocompactsignature) - [1.4.4 verifyCompactSignWithCompressedKey](#144-verifycompactsignwithcompressedkey) - [2. Enumerator](#2-enumerator) - [2.1 DidKeyType](#21-didkeytype) - [2.2 EccCurveType](#22-ecccurvetype) - [2.3 EncryptionType](#23-encryptiontype) - [2.4 EncryptionMode](#24-encryptionmode) - [2.5 SymmetricKeySize](#25-symmetrickeysize) - [2.6 SymmetricPaddingType](#26-symmetricpaddingtype) - [2.7 SymmetricCipherType](#27-symmetricciphertype) - [2.8 DigestType](#28-digesttype) - [2.9 MultiBaseType](#29-multibasetype) - [3. Reference Classes](#3-reference-classes) - [3.1 KeyPairInterface](#31-keypairinterface) - [3.2 CipherInfo](#32-cipherinfo) - [3.3 EcKeyPair](#33-eckeypair) # 1. APIs ## 1.1 CryptoUtils ## 1.1.1 generateKeyPair ### Class Name `CryptoUtils` ### Function Name `generateKeyPair` ### Function Description `Generates a key pair consisting of a public key and a private key.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |-----------|--------------|--------------------------|---------|--------------------| | didKeyType | DidKeyType | Did key type Enum | M | [Link](#21-didkeytype) | ### Output Parameters | Type | Description | **M/O** | **Notes** | |-------------------|--------------------------|---------|----------------------| | KeyPairInterface | KeyPair interface | M | [Link](#31-keypairinterface) | ### Function Declaration ```java KeyPairInterface generateKeyPair(DidKeyType didKeyType) -> throws CryptoException ``` ### Function Usage ```java String didKeyTypeStr = "Secp256r1VerificationKey2018"; DidKeyType didKeyType = DidKeyType.fromString(didKeyTypeStr); KeyPairInterface ecKeyPair = CryptoUtils.generateKeyPair(didKeyType); ```
## 1.1.2 compressPublicKey ### Class Name `CryptoUtils` ### Function Name `compressPublicKey` ### Function Description `Compresses an ECC type public key.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Note** | |--------------------------------|---------------|---------------------------------------------|---------|----------| | unCompressedPublicKeyBytes | byte[] | Uncompressed public key in byte array type | M | | | eccCurveType | EccCurveType | Elliptic curve type Enum | M | [Link](#22-ecccurvetype) | ### Output Parameters | Type | Description | **M/O** | **Note** | |--------|-------------------------------------|---------|----------| | byte[] | Compressed public key in byte array type | M | | ### Function Declaration ```java byte[] compressPublicKey(byte[] unCompressedPublicKeyBytes, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); PublicKey pubKey = (ECPublicKey)keyPair.getPublicKey(); byte[] compressPubKey = CryptoUtils.compressPublicKey(pubKey.getEncoded(), eccCurveType); ```
## 1.1.3 unCompressPublicKey ### Class Name `CryptoUtils` ### Function Name `unCompressPublicKey` ### Function Description `Uncompresses a compressed public key.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |-------------------------|-----------------|------------------------------|---------|------------------------------| | compressedPublicKey | byte[] | compressed public key in byte array type | M | | | eccCurveType | EccCurveType | Elliptic curve type Enum | M | [Link](#22-ecccurvetype) | ### Output Parameters | Type | Description | **M/O** | **Notes** | |---------|---------------------------------------|---------|-------------| | byte[] | Uncompressed public key as a byte array | M | | ### Function Declaration ```java byte[] unCompressPublicKey(byte[] compressedPublicKey, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); String multiBaseTypeStr = "f"; MultiBaseType multiBaseType = MultiBaseType.getByCharacter(multiBaseTypeStr); byte[] compressPubKey = CryptoUtils.compressPublicKey(pubKey.getEncoded(), eccCurveType); byte[] unCompressPubKey = CryptoUtils.unCompressPublicKey(compressPubKey, eccCurveType); ```
## 1.1.4 generateNonce ### Class Name `CryptoUtils` ### Function Name `generateNonce` ### Function Description `Generates a nonce value.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |-----------|------|---------------------------|---------|-------------| | length | int | Length of the nonce to generate | M | | ### Output Parameters | Type | Description | **M/O** | **Notes** | |---------|-----------------------|---------|-------------| | byte[] | Generated nonce | M | | ### Function Declaration ```java byte[] generateNonce(int length) -> throws CryptoException ``` ### Function Usage ```java int nonceLength = 16; byte[] nonce = CryptoUtils.generateNonce(nonceLength); ```
## 1.1.5 generateSalt ### Class Name `CryptoUtils` ### Function Name `generateSalt` ### Function Description `Generates a salt value.` ### Input Parameters n/a ### Output Parameters | Type | Description | **M/O** | **Notes** | |--------|-----------------|---------|-------------| | byte[] | Generated salt value | M | | ### Function Declaration ```java byte[] generateSalt() -> throws CryptoException ``` ### Function Usage ```java byte[] salt = CryptoUtils.generateSalt(); ```
## 1.1.6 generateSharedSecret ### Class Name `CryptoUtils` ### Function Name `generateSharedSecret` ### Function Description `Generates a SharedSecret used for encryption/decryption using ECC keys.`
`Only SECP256R1 and SECP256K1 types of encryption keys are available.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |--------------|--------------|----------------------|---------|----------------------------| | compressedPublicKeyBytes | byte[] | Receiver's compressed public key | M | | | privateKeyBytes | byte[] | Sender's private key | M | | | eccCurveType | EccCurveType | Elliptic curve type Enum | M | [Link](#22-ecccurvetype) | ### Output Parameters | Type | Description | **M/O** | **Notes** | |--------|--------------------|---------|-----------| | byte[] | SharedSecret value | M | | ### Function Declaration ```java byte[] generateSharedSecret(byte[] compressedPublicKeyBytes, byte[] privateKey, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java EccCurveType eccCurveType = ecKeyPair.getECType() byte[] priKey = ((ECPrivateKey) ecKeyPair.getPrivateKey()).getEncoded(); byte[] compressPubKey = CryptoUtils.compressPublicKey(pubKey.getEncoded(), eccCurveType); byte[] sharedSecret = CryptoUtils.generateSharedSecret(compressPubKey, priKey, eccCurveType); ```
## 1.1.7 pbkdf2 ### Class Name `CryptoUtils` ### Function Name `pbkdf2` ### Function Description `Derives an encryption key from the wallet password using the PBKDF2 algorithm.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |-----------|--------|----------------------------|---------|----------| | password | char[] | Password | M | | | salt | byte[] | Encryption salt | M | | | iterator | int | Number of iterations | M | | | keySize | int | Length of the key to be generated | M | | ### Output Parameters | Type | Description | **M/O** | **Notes** | |---------|----------------------------|---------|----------| | byte[] | Key derived through PBKDF2 | M | | ### Function Declaration ```java byte[] pbkdf2(char[] password, byte[] salt, int iterator, int keySize) -> throws CryptoException ``` ### Function Usage ```java byte[] password; byte[] salt = CryptoUtils.generateSalt(); int iterator; int keySize; byte[] derivedKey = CryptoUtils.pbkdf2(char[] password, byte[] salt, int iterator, int keySize) ```
## 1.1.8 encrypt ### Class Name `CryptoUtils` ### Function Name `encrypt` ### Function Description `Encrypts data using the AES algorithm.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |-------------|-------------|------------------------------|---------|--------------------| | source | byte[] | The plaintext data to be encrypted | M | | | cipherInfo | CipherInfo | Encryption information | M | [Link](#32-cipherinfo) | | key | byte[] | Encryption key | M | | | iv | byte[] | Initialization Vector (IV) | M | | ### Output Parameters | Type | Description | **M/O** | **Notes** | |--------|-------------|---------|-----------| | byte[] | Ciphertext | M | | ### Function Declaration ```java byte[] encrypt(byte[] source, CipherInfo cipherInfo, byte[] key, byte[] iv) -> throws CryptoException ``` ### Function Usage ```java String cipherTypeStr = "AES-256-CBC"; String paddingTypeStr = "PKCS5Padding"; SymmetricCipherType symCipherType = SymmetricCipherType.fromString(cipherTypeStr); SymmetricPaddingType symPaddingType = SymmetricPaddingType.fromString(paddingTypeStr); CipherInfo cipherInfo = new CipherInfo(symCipherType, symPaddingType); // Key and iv values derived from SharedSecret byte[] key; byte[] iv; String testData = "EncData"; byte[] encData = CryptoUtils.encrypt(testData.getBytes(), cipherInfo, key, iv); ```
## 1.1.9 decrypt ### Class Name `CryptoUtils` ### Function Name `decrypt` ### Function Description `Decrypts data encrypted using the AES algorithm.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |--------------|-------------|---------------------------|---------|-------------| | cipherText | byte[] | The encrypted data to be decrypted | M | | | cipherInfo | CipherInfo | Encryption information | M | [Link](#32-cipherinfo) | | key | byte[] | Decryption key | M | | | iv | byte[] | Initialization Vector (IV) | M | | ### Output Parameters | Type | Description | **M/O** | **Notes** | |--------|---------------------|---------|-------------| | byte[] | Plaintext data | M | | ### Function Declaration ```java byte[] decrypt(byte[] cipherText, CipherInfo cipherInfo, byte[] key, byte[] iv) -> throws CryptoException ``` ### Function Usage ```java String cipherTypeStr = "AES-256-CBC"; String paddingTypeStr = "PKCS5Padding"; SymmetricCipherType symCipherType = SymmetricCipherType.fromString(cipherTypeStr); SymmetricPaddingType symPaddingType = SymmetricPaddingType.fromString(paddingTypeStr); CipherInfo cipherInfo = new CipherInfo(symCipherType, symPaddingType); // Key and IV derived from SharedSecret byte[] key; byte[] iv; String encodedEncData = "f2516f7865d2e99635a4d6934f3328966ad55d191e02d83da7b8d616b20cb9b0f"; byte[] encData = MultiBaseUtils.decode(encodedEncData); byte[] decData = CryptoUtils.decrypt(encData, cipherInfo, key, iv); ```
## 1.2 DigestUtils ## 1.2.1 getDigest ### Class Name `CryptoUtils` ### Function Name `getDigest` ### Function Description `Hashes data using SHA functions.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |------------|------------|----------------------|---------|-----------| | source | byte[] | Original data | M | | | digestType | DigestType | Hash algorithm type | M | [Link](#28-digesttype) | ### Output Parameters | Type | Description | **M/O** | **Notes** | |--------|---------------|---------|-----------| | byte[] | Hash data | M | | ### Function Declaration ```java byte[] getDigest(byte[] source, DigestType digestType) throws CryptoException ``` ### Function Usage ```java String digestTypeStr = "sha256"; DigestType digestType = DigestType.fromString(digestTypeStr); String testData = "Test Data"; byte[] sha256 = DigestUtils.getDigest(testData.getBytes(), digestType); ```
## 1.3 MultiBaseUtils ## 1.3.1 encode ### Class Name `MultiBaseUtils` ### Function Name `encode` ### Function Description `Converts binary data into characters based on the selected MultiBase type.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |-----------|-----------------|------------------------|---------|-----------| | source | byte[] | Original data | M | | | baseType | MultiBaseType | MultiBase encoding type| M | [Link](#29-multibasetype) | ### Output Parameters | Type | Description | **M/O** | **Notes** | |--------|---------------------|---------|-----------| | String | Encoded data | M | | ### Function Declaration ```java String encode(byte[] source, MultiBaseType baseType) throws CryptoException ``` ### Function Usage ```java String multiBaseTypeStr = "f"; MultiBaseType multiBaseType = MultiBaseType.getByCharacter(multiBaseTypeStr); byte[] testData = "testData".getBytes(); String encoded = MultiBaseUtils.encode(testData, multiBaseType); ```
## 1.3.2 decode ### Class Name `MultiBaseUtils` ### Function Name `decode` ### Function Description `Decodes data encoded in MultiBase format.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |-----------|--------|----------------------|---------|-----------| | multibase | String | Encoded data | M | | ### Output Parameters | Type | Description | **M/O** | **Notes** | |--------|----------------|---------|-----------| | byte[] | Original data | M | | ### Function Declaration ```java byte[] decode(String multibase) throws CryptoException ``` ### Function Usage ```java String multibaseBase16 = "f68656c6c6f2c20776f726c6421"; byte[] source = MultiBaseUtils.decode(multibaseBase16); ```
## 1.4 SignatureUtils ## 1.4.1 generateCompactSignature ### Class Name `SignatureUtils` ### Function Name `generateCompactSignature` ### Function Description `Signs data using an elliptic curve key with the ECDSA algorithm, generates a signature value in ASN.1 DER format, and then converts it to a Compact signature.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |-----------------|----------------|----------------------------------|---------|----------------------------------| | keyPair | EcKeyPair | Elliptic curve key pair | M | [Link](#33-eckeypair) | | hashedSource | byte[] | Hashed source data | M | | | eccCurveType | EccCurveType | Elliptic curve algorithm | M | [Link](#22-ecccurvetype) | ### Output Parameters | Type | Description | **M/O** | **Notes** | |---------|------------------------|---------|-------------| | byte[] | Signed data | M | | ### Function Declaration ```java byte[] generateCompactSignature(EcKeyPair keyPair, byte[] hashedSource, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java String didKeyTypeStr = "Secp256r1VerificationKey2018"; DidKeyType didKeyType = DidKeyType.fromString(didKeyTypeStr); String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); EcKeyPair keyPair = (EcKeyPair) CryptoUtils.generateKeyPair(didKeyType); String rawData = "SignatureData"; String digestTypeStr = "sha256"; DigestType digestType = DigestType.fromString(digestTypeStr); byte[] hashedsource = DigestUtils.getDigest(rawData.getBytes(), digestType); byte[] compactSign = SignatureUtils.generateCompactSignature(keyPair, hashedsource, eccCurveType); ```
## 1.4.2 generateEccSignatureFromHashedData ### Class Name `SignatureUtils` ### Function Name `generateEccSignatureFromHashedData` ### Function Description `Generates a signature value in ASN.1 DER format using an elliptic curve key with the ECDSA algorithm.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |----------------|---------------|------------------------------|---------|----------------------------------| | privateKey | PrivateKey | Signature private key | M | Refer to `java.security.PrivateKey` | | hashedSource | byte[] | Hashed source data | M | | ### Output Parameters | Type | Description | **M/O** | **Notes** | |--------|--------------------|---------|-----------| | byte[] | Signed data | M | | ### Function Declaration ```java byte[] generateEccSignatureFromHashedData(PrivateKey privateKey, byte[] hashedSource) -> throws CryptoException ``` ### Function Usage ```java String didKeyTypeStr = "Secp256r1VerificationKey2018"; DidKeyType didKeyType = DidKeyType.fromString(didKeyTypeStr); String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); EcKeyPair keyPair = (EcKeyPair) CryptoUtils.generateKeyPair(didKeyType); String rawData = "SignatureData"; String digestTypeStr = "sha256"; DigestType digestType = DigestType.fromString(digestTypeStr); byte[] hashedsource = DigestUtils.getDigest(rawData.getBytes(), digestType); byte[] eccSign = SignatureUtils.generateEccSignatureFromHashedData((PrivateKey)keyPair.getPrivateKey(), hashedsource); ```
## 1.4.3 convertToCompactSignature ### Class Name `SignatureUtils` ### Function Name `convertToCompactSignature` ### Function Description `Converts a signature value in ASN.1 DER format to a compact signature.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |----------------|---------------|-----------------------|---------|---------------------------| | publicKey | PublicKey | The public key for signing | M | Refer to java.security.PublicKey | | hashedSource | byte[] | The hashed original data | M | | | signatureBytes | byte[] | ECDSA signature value | M | | | eccCurveType | EccCurveType | Elliptic curve algorithm | M | [Link](#22-ecccurvetype) | ### Output Parameters | Type | Description | **M/O** | **Notes** | |--------|-----------------------|---------|-----------| | byte[] | Compressed signature data | M | | ### Function Declaration ```java byte[] convertToCompactSignature(PublicKey publicKey, byte[] hashedsource, byte[] signatureBytes, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java String didKeyTypeStr = "Secp256r1VerificationKey2018"; DidKeyType didKeyType = DidKeyType.fromString(didKeyTypeStr); String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); EcKeyPair keyPair = (EcKeyPair) CryptoUtils.generateKeyPair(didKeyType); String rawData = "SignatureData"; String digestTypeStr = "sha256"; DigestType digestType = DigestType.fromString(digestTypeStr); byte[] hashedsource = DigestUtils.getDigest(rawData.getBytes(), digestType); byte[] eccSign = SignatureUtils.generateEccSignatureFromHashedData((PrivateKey)keyPair.getPrivateKey(), hashedsource, eccCurveType); byte[] compactSign = SignatureUtils.convertToCompactSignature((PublicKey)keyPair.getPublicKey(), hashedsource, eccSign, eccCurveType); ```
## 1.4.4 verifyCompactSignWithCompressedKey ### Class Name `SignatureUtils` ### Function Name `verifyCompactSignWithCompressedKey` ### Function Description `Verifies the compact signature.` ### Input Parameters | Parameter | Type | Description | **M/O** | **Notes** | |--------------------------|-----------------|--------------------------------|---------|-----------------------------------| | compressedpublicKeyBytes | byte[] | Compressed public key | M | | | hashedsource | byte[] | Hashed original data | M | | | signatureBytes | byte[] | Compressed ECDSA signature | M | | | eccCurveType | EccCurveType | Elliptic curve algorithm | M | [Link](#22-ecccurvetype) | ### Output Parameters void ### Function Declaration ```java void verifyCompactSignWithCompressedKey(byte[] compressedpublicKeyBytes, byte[] hashedsource, byte[] signatureBytes, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); byte[] uncompressedPublicKeyBytes = publicKey.getEncoded(); byte[] compressedPublicKeyBytes = CryptoUtils.compressPublicKey(uncompressedPublicKeyBytes, eccCurveType); // Hashed signature source byte[] hashedSource; // Compact signature value byte[] compactSign; SignatureUtils.verifyCompactSignWithCompressedKey(compressedPublicKeyBytes, hashedsource, compactSign, eccCurveType); ```
# Enumerator ## 2.1 DidKeyType ### Declaration ```java public enum DidKeyType { RSA_VERIFICATION_KEY_2018("RsaVerificationKey2018"), SECP256K1_VERIFICATION_KEY_2018("Secp256k1VerificationKey2018"), SECP256R1_VERIFICATION_KEY_2018("Secp256r1VerificationKey2018"); } ``` ### Usage ```java String didKeyTypeStr = "Secp256r1VerificationKey2018"; DidKeyType didKeyType = DidKeyType.fromString(didKeyTypeStr); ``` ## 2.2 EccCurveType ### Declaration ```java public enum EccCurveType { Secp256k1("Secp256k1"), Secp256r1("Secp256r1"); } ``` ### Usage ```java String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); ``` ## 2.3 EncryptionType ### Declaration ```java public enum EncryptionType { AES("AES"); } ``` ### Usage ```java String encryptionTypeStr = "AES"; EncryptionType encryptionType = EncryptionType.fromString(encryptionTypeStr); ``` ## 2.4 EncryptionMode ### Declaration ```java public enum EncryptionMode { CBC("CBC"), ECB("ECB"); } ``` ### Usage ```java String encryptionModeStr = "CBC"; EncryptionMode encryptionMode = EncryptionMode.fromString(encryptionModeStr); ``` ## 2.5 SymmetricKeySize ### Declaration ```java public enum SymmetricKeySize { Size128(128), Size256(256); } ``` ### Usage ```java int symmetricKeySizeValue = 256; SymmetricKeySize symmetricKeySize = SymmetricKeySize.fromString(symmetricKeySizeValue); ``` ## 2.6 SymmetricPaddingType ### Declaration ```java public enum SymmetricPaddingType { NOPAD("NoPadding"), PKCS5("PKCS5Padding"); } ``` ### Usage ```java String symmetricPaddingTypeStr = "PKCS5Padding"; SymmetricPaddingType symmetricPaddingType = SymmetricPaddingType.fromString(symmetricPaddingTypeStr); ``` ## 2.7 SymmetricCipherType ### Declaration ```java public enum SymmetricCipherType { AES_128_CBC("AES-128-CBC"), AES_128_ECB("AES-128-ECB"), AES_256_CBC("AES-256-CBC"), AES_256_ECB("AES-256-ECB"); } ``` ### Usage ```java String symmetricCipherTypeStr = "AES-256-CBC"; SymmetricCipherType symmetricCipherType = SymmetricCipherType.fromString(symmetricCipherTypeStr); ``` ## 2.8 DigestType ### Declaration ```java public enum DigestType { SHA256("sha256"), SHA512("sha512"), SHA384("sha384"); } ``` ### Usage ```java String digestTypeStr = "sha256"; DigestType digestType = DigestType.fromString(digestTypeStr); ``` ## 2.9 MultiBaseType ### Declaration ```java public enum MultiBaseType { base16("f"), base16upper("F"), base58btc("z"), base64url("u"), base64("m"); } ``` ### Usage ```java String multiBaseTypeStr = "f"; MultiBaseType multiBaseType = MultiBaseType.getByCharacter(multiBaseTypeStr); ```
# 3. Reference Classes ## 3.1 KeyPairInterface ### Declaration ```java public interface KeyPairInterface { public PublicKey getPublicKey(); public void setPublicKey(PublicKey publicKey); public PrivateKey getPrivateKey(); public void setPrivateKey(PrivateKey privateKey); } // For PublicKey, PrivateKey types, see java.security.PublicKey, PrivateKey ``` ## 3.2 CipherInfo ### Declaration ```java public class CipherInfo { private EncryptionType type; private EncryptionMode mode; private SymmetricKeySize size; private SymmetricPaddingType padding; public CipherInfo(SymmetricCipherType cipherType, SymmetricPaddingType paddingType) throws CryptoException {} } ``` ### Usage ```java String cipherTypeStr = "AES-256-CBC"; String paddingTypeStr = "PKCS5Padding"; SymmetricCipherType symCipherType = SymmetricCipherType.fromString(cipherTypeStr); SymmetricPaddingType symPaddingType = SymmetricPaddingType.fromString(paddingTypeStr); CipherInfo cipherInfo = new CipherInfo(symCipherType, symPaddingType); ``` ### Property | Parameter | Type | Description | **M/O** | **Notes** | |-----------------|-----------------------|-----------------------------|---------|-----------------------------------| | type | EncryptionType | Encryption algorithm type | M | [Link](#23-encryptiontype) | | mode | EncryptionMode | Block cipher mode | M | [Link](#24-encryptionmode) | | size | SymmetricKeySize | Key length | M | [Link](#25-symmetrickeysize) | | paddingType | SymmetricPaddingType | Padding type | M | [Link](#26-symmetricpaddingtype) | | cipherType | SymmetricCipherType | Cipher type | M | [Link](#27-symmetricciphertype) | ## 3.3 EcKeyPair ### Declaration ```java public class EcKeyPair implements KeyPairInterface{ EccCurveType eccCurveType; private ECPublicKey publicKey; private ECPrivateKey privateKey; } ``` ### Property | Parameter | Type | Description | **M/O** | **Notes** | |--------------|-----------------|----------------------------------|---------|-----------| | eccCurveType | EccCurveType | Elliptic Curve Type Enum | M | [Link](#22-ecccurvetype) | | publicKey | PublicKey | Elliptic Curve Public Key | M | Refer to java.security.ECPublicKey | | privateKey | PrivateKey | Elliptic Curve Private Key | M | Refer to java.security.ECPrivateKey | ================================================ FILE: docs/api/CRYPTO_SDK-SERVER_API_ko.md ================================================ --- puppeteer: pdf: format: A4 displayHeaderFooter: true landscape: false scale: 0.8 margin: top: 1.2cm right: 1cm bottom: 1cm left: 1cm image: quality: 100 fullPage: false --- Crypto SDK Server API == - 주제: Crypto SDK Server API - 작성: 여승재 - 일자: 2024-08-30 - 버전: v1.0.0 | 버전 | 일자 | 변경 내용 | | ------ | ---------- | -------------------------| | v1.0.0 | 2024-08-30 | 초기 작성 |
# 목차 - [1. APIs](#1-apis) - [1.1 CryptoUtils](#11-cryptoutils) - [1.1.1 generateKeyPair](#111-generatekeypair) - [1.1.2 compressPublicKey](#112-compresspublickey) - [1.1.3 unCompressPublicKey](#113-uncompresspublickey) - [1.1.4 generateNonce](#114-generatenonce) - [1.1.5 generateSalt](#115-generatesalt) - [1.1.6 generateSharedSecret](#116-generatesharedsecret) - [1.1.7 pbkdf2](#117-pbkdf2) - [1.1.8 encrypt](#118-encrypt) - [1.1.9 decrypt](#119-decrypt) - [1.2 DigestUtils](#12-digestutils) - [1.2.1 getDigest](#121-getdigest) - [1.3 MultiBaseUtils](#13-multibaseutils) - [1.3.1 encode](#131-encode) - [1.3.2 decode](#132-decode) - [1.4 SignatureUtils](#14-signatureutils) - [1.4.1 generateCompactSignature](#141-generatecompactsignature) - [1.4.2 generateEccSignatureFromHashedData](#142-generateeccsignaturefromhasheddata) - [1.4.3 convertToCompactSignature](#143-converttocompactsignature) - [1.4.4 verifyCompactSignWithCompressedKey](#144-verifycompactsignwithcompressedkey) - [2. Enumerator](#2-enumerator) - [2.1 DidKeyType](#21-didkeytype) - [2.2 EccCurveType](#22-ecccurvetype) - [2.3 EncryptionType](#23-encryptiontype) - [2.4 EncryptionMode](#24-encryptionmode) - [2.5 SymmetricKeySize](#25-symmetrickeysize) - [2.6 SymmetricPaddingType](#26-symmetricpaddingtype) - [2.7 SymmetricCipherType](#27-symmetricciphertype) - [2.8 DigestType](#28-digesttype) - [2.9 MultiBaseType](#29-multibasetype) - [3. 참조 클래스](#3-참조-클래스) - [3.1 KeyPairInterface](#31-keypairinterface) - [3.2 CipherInfo](#32-cipherinfo) - [3.3 EcKeyPair](#33-eckeypair) # 1. APIs ## 1.1 CryptoUtils ## 1.1.1 generateKeyPair ### Class Name `CryptoUtils` ### Function Name `generateKeyPair` ### Function Introduction `공개키-개인키 쌍으로 이루어진 키 페어를 생성합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | didKeyType | DidKeyType | Did 키 타입 Enum |M| [Link](#21-didkeytype)| ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | KeyPairInterface | KeyPair 인터페이스 |M| [Link](#31-keypairinterface) | ### Function Declaration ```java KeyPairInterface generateKeyPair(DidKeyType didKeyType) -> throws CryptoException ``` ### Function Usage ```java String didKeyTypeStr = "Secp256r1VerificationKey2018"; DidKeyType didKeyType = DidKeyType.fromString(didKeyTypeStr); KeyPairInterface ecKeyPair = CryptoUtils.generateKeyPair(didKeyType); ```
## 1.1.2 compressPublicKey ### Class Name `CryptoUtils` ### Function Name `compressPublicKey` ### Function Introduction `ECC 타입 공개키를 압축합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | unCompressedPublicKeyBytes | byte[] | 바이트 배열 타입의 압축되지 않은 공개키 |M|| | eccCurveType | EccCurveType | 타원 곡선 타입 Enum |M| [Link](#22-ecccurvetype) | ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 바이트 배열 타입의 압축된 공개키 |M| | ### Function Declaration ```java byte[] compressPublicKey(byte[] unCompressedPublicKeyBytes, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); PublicKey pubKey = (ECPublicKey)keyPair.getPublicKey(); byte[] compressPubKey = CryptoUtils.compressPublicKey(pubKey.getEncoded(), eccCurveType); ```
## 1.1.3 unCompressPublicKey ### Class Name `CryptoUtils` ### Function Name `unCompressPublicKey` ### Function Introduction `압축된 공개키를 압축 해제합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | compressedPublicKey | byte[] | 압축된 공개키 |M|| | eccCurveType | EccCurveType | 타원 곡선 타입 Enum |M| [Link](#22-ecccurvetype) | ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 바이트 배열 타입의 압축 해제된 공개키 |M| | ### Function Declaration ```java byte[] unCompressPublicKey(byte[] compressedPublicKey, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); String multiBaseTypeStr = "f"; MultiBaseType multiBaseType = MultiBaseType.getByCharacter(multiBaseTypeStr); byte[] compressPubKey = CryptoUtils.compressPublicKey(pubKey.getEncoded(), eccCurveType); byte[] unCompressPubKey = CryptoUtils.unCompressPublicKey(compressPubKey, eccCurveType); ```
## 1.1.4 generateNonce ### Class Name `CryptoUtils` ### Function Name `generateNonce` ### Function Introduction `Nonce 값을 생성합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | length | int | 생성할 논스 길이 |M|| ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 생성된 논스 |M| | ### Function Declaration ```java byte[] generateNonce(int length) -> throws CryptoException ``` ### Function Usage ```java int nonceLength = 16; byte[] nonce = CryptoUtils.generateNonce(nonceLength); ```
## 1.1.5 generateSalt ### Class Name `CryptoUtils` ### Function Name `generateSalt` ### Function Introduction `salt 값을 생성합니다.` ### Input Parameters n/a ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 생성된 salt값 |M| | ### Function Declaration ```java byte[] generateSalt() -> throws CryptoException ``` ### Function Usage ```java byte[] salt = CryptoUtils.generateSalt(); ```
## 1.1.6 generateSharedSecret ### Class Name `CryptoUtils` ### Function Name `generateSharedSecret` ### Function Introduction `ECC 키를 사용해 암/복호화에 사용될 SharedSecret을 생성합니다.`
`암호화 키는 SECP256R1, SECP256K1 종류만 사용 가능합니다` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | compressedPublicKeyBytes | byte[] | 수신자 압축 공개키 |M|| | privateKeyBytes | byte[] | 송신자 개인키 |M| | | eccCurveType | EccCurveType | 타원 곡선 타입 Enum |M| [Link](#22-ecccurvetype) | ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | SharedSecret 값 |M| | ### Function Declaration ```java byte[] generateSharedSecret(byte[] compressedPublicKeyBytes, byte[] privateKey, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java EccCurveType eccCurveType = ecKeyPair.getECType() byte[] priKey = ((ECPrivateKey) ecKeyPair.getPrivateKey()).getEncoded(); byte[] compressPubKey = CryptoUtils.compressPublicKey(pubKey.getEncoded(), eccCurveType); byte[] sharedSecret = CryptoUtils.generateSharedSecret(compressPubKey, priKey, eccCurveType); ```
## 1.1.7 pbkdf2 ### Class Name `CryptoUtils` ### Function Name `pbkdf2` ### Function Introduction `월렛 패스워드를 PBKDF2 알고리즘을 사용해서 암호화 키를 유도합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | password | char[] | 패스워드 |M|| | salt | byte[] | 암호화 salt |M| | | iterator | int | 반복 횟수 |M| | | keySize | int | 생성할 키 길이 |M| | ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | PBKDF2를 통해 유도한 키 |M| | ### Function Declaration ```java byte[] pbkdf2(char[] password, byte[] salt, int iterator, int keySize) -> throws CryptoException ``` ### Function Usage ```java byte[] password; byte[] salt = CryptoUtils.generateSalt(); int iterator; int keySize; byte[] derivedKey = CryptoUtils.pbkdf2(char[] password, byte[] salt, int iterator, int keySize) ```
## 1.1.8 encrypt ### Class Name `CryptoUtils` ### Function Name `encrypt` ### Function Introduction `AES 알고리즘으로 데이터를 암호화 합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | source | byte[] | 암호화 할 원문 데이터 |M|| | cipherInfo | CipherInfo | 암호화 정보 |M| [Link](#32-cipherinfo) | | key | byte[] | 암호화 키 |M|| | iv | byte[] | 초기화 벡터(IV)값 |M| | ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 암호문 |M| | ### Function Declaration ```java byte[] encrypt(byte[] source, CipherInfo cipherInfo, byte[] key, byte[] iv) -> throws CryptoException ``` ### Function Usage ```java String cipherTypeStr = "AES-256-CBC"; String paddingTypeStr = "PKCS5Padding"; SymmetricCipherType symCipherType = SymmetricCipherType.fromString(cipherTypeStr); SymmetricPaddingType symPaddingType = SymmetricPaddingType.fromString(paddingTypeStr); CipherInfo cipherInfo = new CipherInfo(symCipherType, symPaddingType); // SharedSecret으로 부터 유도된 key와 iv값 byte[] key; byte[] iv; String testData = "EncData"; byte[] encData = CryptoUtils.encrypt(testData.getBytes(), cipherInfo, key, iv); ```
## 1.1.9 decrypt ### Class Name `CryptoUtils` ### Function Name `decrypt` ### Function Introduction `AES 알고리즘으로 암호화 된 데이터를 복호화 합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | cipherText | byte[] | 복호화 할 암호화 데이터 |M|| | cipherInfo | CipherInfo | 암호화 정보 |M| [Link](#32-cipherinfo) | | key | byte[] | 복호화 키 |M|| | iv | byte[] | 초기화 벡터(IV)값 |M| | ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 원문 데이터 |M| | ### Function Declaration ```java byte[] decrypt(byte[] cipherText, CipherInfo cipherInfo, byte[] key, byte[] iv) -> throws CryptoException ``` ### Function Usage ```java String cipherTypeStr = "AES-256-CBC"; String paddingTypeStr = "PKCS5Padding"; SymmetricCipherType symCipherType = SymmetricCipherType.fromString(cipherTypeStr); SymmetricPaddingType symPaddingType = SymmetricPaddingType.fromString(paddingTypeStr); CipherInfo cipherInfo = new CipherInfo(symCipherType, symPaddingType); // SharedSecret으로 부터 유도된 key와 iv값 byte[] key; byte[] iv; String encodedEncData = "f2516f7865d2e99635a4d6934f3328966ad55d191e02d83da7b8d616b20cb9b0f"; byte[] encData = MultiBaseUtils.decode(encodedEncData); byte[] decData = CryptoUtils.decrypt(encData, cipherInfo, key, iv); ```
## 1.2 DigestUtils ## 1.2.1 getDigest ### Class Name `CryptoUtils` ### Function Name `getDigest` ### Function Introduction `SHA 함수를 사용해 데이터를 해시화 합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | source | byte[] | 원문 데이터 |M|| | digestType | DigestType | 해시 알고리즘 타입 |M| [Link](#28-digesttype) | ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 해시 데이터 |M| | ### Function Declaration ```java byte[] getDigest(byte[] source, DigestType digestType) -> throws CryptoException ``` ### Function Usage ```java String digestTypeStr = "sha256"; DigestType digestType = DigestType.fromString(digestTypeStr); String testData = "Test Data"; byte[] sha256 = DigestUtils.getDigest(testData.getBytes(), digestType); ```
## 1.3 MultiBaseUtils ## 1.3.1 encode ### Class Name `MultiBaseUtils` ### Function Name `encode` ### Function Introduction `선택한 MultiBase 타입에 따라 이진 데이터를 문자로 변환합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | source | byte[] | 원문 데이터 |M|| | baseType | MultiBaseType | MultiBase 인코딩 타입 |M| [Link](#29-multibasetype) | ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | String | 인코딩 된 데이터 |M| | ### Function Declaration ```java String encode(byte[] source, MultiBaseType baseType) -> throws CryptoException ``` ### Function Usage ```java String multiBaseTypeStr = "f"; MultiBaseType multiBaseType = MultiBaseType.getByCharacter(multiBaseTypeStr); byte[] testData = "testData".getBytes(); String encoded = MultiBaseUtils.encode(testData, multiBaseType); ```
## 1.3.2 decode ### Class Name `MultiBaseUtils` ### Function Name `decode` ### Function Introduction `MultiBase 인코딩 된 데이터를 디코딩 합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | multibase | String | 인코딩 된 데이터 |M|| ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 원문 데이터 |M| | ### Function Declaration ```java byte[] decode(String multibase) -> throws CryptoException ``` ### Function Usage ```java String multibaseBase16 = "f68656c6c6f2c20776f726c6421"; byte[] source = MultiBaseUtils.decode(multibaseBase16); ```
## 1.4 SignatureUtils ## 1.4.1 generateCompactSignature ### Class Name `SignatureUtils` ### Function Name `generateCompactSignature` ### Function Introduction `ECDSA 알고리즘을 사용해 타원 곡선 키로 데이터를 서명하여 ASN.1 DER 형식의 서명값 생성 후 Compact 서명으로 변환합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | keyPair | EcKeyPair | 타원 곡선 키 페어 |M| [Link](#33-eckeypair) | | hashedSource | byte[] | 해시된 원문 데이터 |M|| | eccCurveType | EccCurveType | 타원 곡선 알고리즘 |M| [Link](#22-ecccurvetype) | ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 서명 된 데이터 |M| | ### Function Declaration ```java byte[] generateCompactSignature(EcKeyPair keyPair, byte[] hashedSource, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java String didKeyTypeStr = "Secp256r1VerificationKey2018"; DidKeyType didKeyType = DidKeyType.fromString(didKeyTypeStr); String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); EcKeyPair keyPair = (EcKeyPair) CryptoUtils.generateKeyPair(didKeyType); String rawData = "SignatureData"; String digestTypeStr = "sha256"; DigestType digestType = DigestType.fromString(digestTypeStr); byte[] hashedsource = DigestUtils.getDigest(rawData.getBytes(), digestType); byte[] compactSign = SignatureUtils.generateCompactSignature(keyPair, hashedsource, eccCurveType); ```
## 1.4.2 generateEccSignatureFromHashedData ### Class Name `SignatureUtils` ### Function Name `generateEccSignatureFromHashedData` ### Function Introduction `ECDSA 알고리즘을 사용해 타원 곡선 키로 ASN.1 DER 형식의 서명값을 생성합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | privateKey | PrivateKey | 서명 개인키 |M| java.security.PrivateKey 참조 | | hashedSource | byte[] | 해시된 원문 데이터 |M|| ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 서명 된 데이터 |M| | ### Function Declaration ```java byte[] generateEccSignatureFromHashedData(PrivateKey privateKey, byte[] hashedSource) -> throws CryptoException ``` ### Function Usage ```java String didKeyTypeStr = "Secp256r1VerificationKey2018"; DidKeyType didKeyType = DidKeyType.fromString(didKeyTypeStr); String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); EcKeyPair keyPair = (EcKeyPair) CryptoUtils.generateKeyPair(didKeyType); String rawData = "SignatureData"; String digestTypeStr = "sha256"; DigestType digestType = DigestType.fromString(digestTypeStr); byte[] hashedsource = DigestUtils.getDigest(rawData.getBytes(), digestType); byte[] eccSign = SignatureUtils.generateEccSignatureFromHashedData((PrivateKey)keyPair.getPrivateKey(), hashedsource); ```
## 1.4.3 convertToCompactSignature ### Class Name `SignatureUtils` ### Function Name `convertToCompactSignature` ### Function Introduction `ASN.1 DER 형식의 서명값을 Compact 서명으로 변환합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | publicKey | PublicKey | 서명 공개키 |M| java.security.PublicKey 참조 | | hashedSource | byte[] | 해시된 원문 데이터 |M|| | signatureBytes | byte[] | ECDSA 서명값 |M|| | eccCurveType | EccCurveType | 타원 곡선 알고리즘 |M| [Link](#22-ecccurvetype) | ### Output Parameters | Type | Description |**M/O** | **비고** | |------|----------------------------|---------|---------| | byte[] | 압축된 서명 데이터 |M| | ### Function Declaration ```java byte[] convertToCompactSignature(PublicKey publicKey, byte[] hashedsource, byte[] signatureBytes, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java String didKeyTypeStr = "Secp256r1VerificationKey2018"; DidKeyType didKeyType = DidKeyType.fromString(didKeyTypeStr); String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); EcKeyPair keyPair = (EcKeyPair) CryptoUtils.generateKeyPair(didKeyType); String rawData = "SignatureData"; String digestTypeStr = "sha256"; DigestType digestType = DigestType.fromString(digestTypeStr); byte[] hashedsource = DigestUtils.getDigest(rawData.getBytes(), digestType); byte[] eccSign = SignatureUtils.generateEccSignatureFromHashedData((PrivateKey)keyPair.getPrivateKey(), hashedsource, eccCurveType); byte[] compactSign = SignatureUtils.convertToCompactSignature((PublicKey)keyPair.getPublicKey(), hashedsource, eccSign, eccCurveType); ```
## 1.4.4 verifyCompactSignWithCompressedKey ### Class Name `SignatureUtils` ### Function Name `verifyCompactSignWithCompressedKey` ### Function Introduction `Compact 서명값을 검증합니다.` ### Input Parameters | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | compressedpublicKeyBytes | byte[] | 압축된 공개키 |M|| | hashedsource | byte[] | 해시된 원문 데이터 |M|| | signatureBytes | byte[] | 압축된 ECDSA 서명값 |M|| | eccCurveType | EccCurveType | 타원 곡선 알고리즘 |M| [Link](#22-ecccurvetype) | ### Output Parameters void ### Function Declaration ```java void verifyCompactSignWithCompressedKey(byte[] compressedpublicKeyBytes, byte[] hashedsource, byte[] signatureBytes, EccCurveType eccCurveType) -> throws CryptoException ``` ### Function Usage ```java String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); byte[] uncompressedPublicKeyBytes = publicKey.getEncoded(); byte[] compressedPublickeyBytes = CryptoUtils.compressPublicKey(uncompressedPublicKeyBytes, eccCurveType); // 해시된 서명원문 byte[] hashedsource; // Compact 서명값 byte[] compactSign; SignatureUtils.verifyCompactSignWithCompressedKey(compressedPublickeyBytes, hashedsource, compactSign, eccCurveType); ```
# Enumerator ## 2.1 DidKeyType ### Declaration ```java public enum DidKeyType { RSA_VERIFICATION_KEY_2018("RsaVerificationKey2018"), SECP256K1_VERIFICATION_KEY_2018("Secp256k1VerificationKey2018"), SECP256R1_VERIFICATION_KEY_2018("Secp256r1VerificationKey2018"); } ``` ### Usage ```java String didKeyTypeStr = "Secp256r1VerificationKey2018"; DidKeyType didKeyType = DidKeyType.fromString(didKeyTypeStr); ``` ## 2.2 EccCurveType ### Declaration ```java public enum EccCurveType { Secp256k1("Secp256k1"), Secp256r1("Secp256r1"); } ``` ### Usage ```java String eccCurveTypeStr = "Secp256r1"; EccCurveType eccCurveType = EccCurveType.fromString(eccCurveTypeStr); ``` ## 2.3 EncryptionType ### Declaration ```java public enum EncryptionType { AES("AES"); } ``` ### Usage ```java String encryptionTypeStr = "AES"; EncryptionType encryptionType = EncryptionType.fromString(encryptionTypeStr); ``` ## 2.4 EncryptionMode ### Declaration ```java public enum EncryptionMode { CBC("CBC"), ECB("ECB"); } ``` ### Usage ```java String encryptionModeStr = "CBC"; EncryptionMode encryptionMode = EncryptionMode.fromString(encryptionModeStr); ``` ## 2.5 SymmetricKeySize ### Declaration ```java public enum SymmetricKeySize { Size128(128), Size256(256); } ``` ### Usage ```java int symmetricKeySizeValue = 256; SymmetricKeySize symmetricKeySize = SymmetricKeySize.fromString(symmetricKeySizeValue); ``` ## 2.6 SymmetricPaddingType ### Declaration ```java public enum SymmetricPaddingType { NOPAD("NoPadding"), PKCS5("PKCS5Padding"); } ``` ### Usage ```java String symmetricPaddingTypeStr = "PKCS5Padding"; SymmetricPaddingType symmetricPaddingType = SymmetricPaddingType.fromString(symmetricPaddingTypeStr); ``` ## 2.7 SymmetricCipherType ### Declaration ```java public enum SymmetricCipherType { AES_128_CBC("AES-128-CBC"), AES_128_ECB("AES-128-ECB"), AES_256_CBC("AES-256-CBC"), AES_256_ECB("AES-256-ECB"); } ``` ### Usage ```java String symmetricCipherTypeStr = "AES-256-CBC"; SymmetricCipherType symmetricCipherType = SymmetricCipherType.fromString(symmetricCipherTypeStr); ``` ## 2.8 DigestType ### Declaration ```java public enum DigestType { SHA256("sha256"), SHA512("sha512"), SHA384("sha384"); } ``` ### Usage ```java String digestTypeStr = "sha256"; DigestType digestType = DigestType.fromString(digestTypeStr); ``` ## 2.9 MultiBaseType ### Declaration ```java public enum MultiBaseType { base16("f"), base16upper("F"), base58btc("z"), base64url("u"), base64("m"); } ``` ### Usage ```java String multiBaseTypeStr = "f"; MultiBaseType multiBaseType = MultiBaseType.getByCharacter(multiBaseTypeStr); ```
# 3. 참조 클래스 ## 3.1 KeyPairInterface ### Declaration ```java public interface KeyPairInterface { public Object getPublicKey(); public void setPublicKey(Object publicKey); public Object getPrivateKey(); public void setPrivateKey(Object privateKey); } ``` ## 3.2 CipherInfo ### Declaration ```java public class CipherInfo { private EncryptionType type; private EncryptionMode mode; private SymmetricKeySize size; private SymmetricPaddingType padding; public CipherInfo(SymmetricCipherType cipherType, SymmetricPaddingType paddingType) throws CryptoException {} } ``` ### Usage ```java String cipherTypeStr = "AES-256-CBC"; String paddingTypeStr = "PKCS5Padding"; SymmetricCipherType symCipherType = SymmetricCipherType.fromString(cipherTypeStr); SymmetricPaddingType symPaddingType = SymmetricPaddingType.fromString(paddingTypeStr); CipherInfo cipherInfo = new CipherInfo(symCipherType, symPaddingType); ``` ### Property | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | type | EncryptionType | 암호화 알고리즘 타입 |M| [Link](#23-encryptiontype)| | mode | EncryptionMode | 블록 암호화 모드 |M| [Link](#24-encryptionmode) | | size | SymmetricKeySize | 키 길이 |M| [Link](#25-symmetrickeysize) | | paddingType | SymmetricPaddingType | 패딩 타입 |M| [Link](#26-symmetricpaddingtype) | | cipherType | SymmetricCipherType | Cipher 타입 |M| [Link](#27-symmetricciphertype) | ## 3.3 EcKeyPair ### Declaration ```java public class EcKeyPair implements KeyPairInterface{ EccCurveType eccCurveType; private ECPublicKey publicKey; private ECPrivateKey privateKey; } ``` ### Property | Parameter | Type | Description | **M/O** | **비고** | |-----------|--------|----------------------------|---------|---------| | eccCurveType | EccCurveType | 타원 곡선 타입 Enum |M| [Link](#22-ecccurvetype)| | publicKey | ECPublicKey | 타원 곡선 공개키 |M| java.security.ECPublicKey 참조 | | privateKey | ECPrivateKey | 타원 곡선 개인키 |M| java.security.ECPrivateKey 참조 | ================================================ FILE: docs/api/CryptoSDKError.md ================================================ --- puppeteer: pdf: format: A4 displayHeaderFooter: true landscape: false scale: 0.8 margin: top: 1.2cm right: 1cm bottom: 1cm left: 1cm image: quality: 100 fullPage: false --- Crytpo SDK Error == - Topic: CryptoSDKError - Author: Jongyun Baek - Date: 2024-08-27 - Version: v1.0.0 | Version | Date | Changes | | ---------------- | ---------- | ------------------------ | | v1.0.0 | 2024-08-20 | Initial version |
# Table of Contents - [Model](#model) - [Error Response](#error-response) - [Error Code](#error-code) - [1.1. DigestUtil (01xxx)](#11-digestutil01xxx) - [1.2. CryptoUtil (02xxx)](#12-cryptoutil02xxx) - [1.3. MultibaseUtil (03xxx)](#13-multibaseutil03xxx) - [1.4. SignatureUtil (04xxx)](#14-signatureutil04xxx) # Model ## Error Response ### Description ``` Error struct for Crypto SDK. It has code and message pair. Code starts with SSDKCRT. ``` ### Declaration ```java public class ErrorResponse { private final String code; private final String description; } ``` ### Property | Name | Type | Description | **M/O** | **Note** | |--------------------|------------|----------------------------------------|---------|-----------------------| | code | String | Error code. It starts with SSDKCRT | M | | | message | String | Error description | M | |
# Error Code ## 1. Crypto SDK ### 1.1. DigestUtil(01xxx) | Error Code | Error Message | Description | Action Required | |--------------|----------------------------------------------|------------------|-----------------------------------------------------------| | SSDKCRT01000 | Hash type is invalid. | - | Check the type of hash. | | SSDKCRT01001 | Failed to generate hash. | - | Check the name of hash algorithme. | | SSDKCRT01002 | Failed to generate secure random. | - | Check the name of algorithme for generating secure random.| | SSDKCRT01003 | Hash type or Source is null. | - | Ensure the source and hash type are not null. |
### 1.2. CryptoUtil(02xxx) | Error Code | Error Message | Description | Action Required | |--------------|----------------------------------------------|------------------|-----------------------------------------------------------------------------------------------------| | SSDKCRT02000 | Invalid DID Key Type. | - | Check the type of DID key. | | SSDKCRT02001 | Failed to generate random key. | - | Check the key algorithm to generate. | | SSDKCRT02002 | Failed to Compress PublicKey. | - | Verify correct algorithm/provider names, proper library setup, and valid public key format. | | SSDKCRT02003 | Failed to UnCompress PublicKey. | - | Verify correct algorithm/provider names, proper library setup, and valid public key format. | | SSDKCRT02004 | Failed to generate shared secret. | - | Verify correct setup, valid key data, and accurate algorithm/provider names. | | SSDKCRT02005 | Cipher type is invalid. | - | Ensure that the cipherType provided is valid and supported by the implementation. | | SSDKCRT02006 | Failed to Encrypt, Decrypt. | - | Verify the cipher, key, padding, and IV are correctly configured. |
### 1.3. MultibaseUtil(03xxx) | Error Code | Error Message | Description | Action Required | |--------------|----------------------------------------------|------------------|------------------------------------------------------------------------------------------------------------------| | SSDKCRT03000 | Multibase encoding type is invalid. | - | Check that the selected multibase encoding type is valid. | | SSDKCRT03001 | Multibase decoding type is invalid. | - | Ensure that the decoding type corresponds to the correct multibase encoding format and is implemented correctly. |
### 1.4. SignatureUtil(04xxx) | Error Code | Error Message | Description | Action Required | |--------------|------------------------------------------------------|------------------|--------------------------------------------------------------------------------------------------------------------------| | SSDKCRT04000 | Failed to recover valid recovery ID. | - | Verify that the recovery ID is generated correctly and corresponds to the expected format. | | SSDKCRT04001 | The provided input value is invalid. | - | Ensure that all provided input values are valid and within the expected range or format. | | SSDKCRT04002 | This indicates that the ASN.1 sequence is invalid. | - | Confirm that the ASN.1 sequence is properly structured and adheres to the required specifications. | | SSDKCRT04003 | It is not a compact sign. | - | Validate that the sign value is in the correct compact format and properly encoded. | | SSDKCRT04004 | The publicKey is not in compressed public key format.| - | Make sure that the public key is in the correct compressed format. | | SSDKCRT04005 | RecoveryKey creation failed. | - | Investigate the recovery process and verify that all required data for creating the RecoveryKey is correct and available.| | SSDKCRT04006 | RecoveryKey and publicKey do not match. | - | Ensure that the generated RecoveryKey corresponds accurately to the provided publicKey. |
================================================ FILE: signatures/version1/cla.json ================================================ { "signedContributors": [ { "name": "sjyeo98", "id": 180237692, "comment_id": 2406915307, "created_at": "2024-10-11T08:37:15Z", "repoId": 804724106, "pullRequestNo": 4 } ] } ================================================ FILE: source/did-crypto-sdk-server/.gitignore ================================================ HELP.md .gradle build/ !gradle/wrapper/gradle-wrapper.jar !**/src/main/**/build/ !**/src/test/**/build/ ### STS ### .apt_generated .classpath .factorypath .project .settings .springBeans .sts4-cache bin/ !**/src/main/**/bin/ !**/src/test/**/bin/ ### IntelliJ IDEA ### .idea *.iws *.iml *.ipr out/ !**/src/main/**/out/ !**/src/test/**/out/ ### NetBeans ### /nbproject/private/ /nbbuild/ /dist/ /nbdist/ /.nb-gradle/ ### VS Code ### .vscode/ ================================================ FILE: source/did-crypto-sdk-server/README.md ================================================ # Server Crypto SDK Guide This document is a guide to using the OpenDID Server Crypto SDK, It provides the necessary decryption functions for Open DID as Crypto, Degest, MultiBase, and Signature Utils. ## S/W Specifications | Component | Requirement | |------|----------------------------| | Language | Java 21| | Build System | Gradle 8.8 |
## Build Method : Create a JAR file based on the build.gradle file of this SDK project. 1. Open the `build.gradle` file of your project and add a task from the configuration file as shown below. ```groovy plugins { id 'java' } group = 'org.omnione.did' java { sourceCompatibility = '21' } jar { archiveBaseName.set('did-crypto-sdk-server') archiveVersion.set('2.0.0') archiveClassifier.set('') } repositories { mavenCentral() } dependencies { implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' } ``` 2. Open the `Gradle` tab in IDE and run the project's `Task > Build > Clean and Build` task, or type `./gradlew clean & build` in a terminal. 3. Once the execution is complete, the `did-crypto-sdk-server-2.0.0.jar` file will be generated in the `{projetPath}/build/libs/` folder.
## SDK Application Method 1. Copy the `did-crypto-sdk-server-2.0.0.jar` file to the libs of the server project. 2. Add the following dependencies to the `build.gradle` of the server project. ```groovy implementation files('libs/did-crypto-sdk-server-2.0.0.jar') implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' ``` 3. Sync `Gradle` to ensure the dependencies are properly added.
## API Specification | Classification | API Document Link | |------|----------------------------| | CryptoUtils | [Crypto SDK Server API - CryptoUtils ](/docs/api/CRYPTO_SDK-SERVER_API.md#11-cryptoutils) | | DigestUtils | [Crypto SDK Server API - DigestUtils ](/docs/api/CRYPTO_SDK-SERVER_API.md#12-digestutils) | | MultiBaseUtils | [Crypto SDK Server API - MultiBaseUtils](/docs/api/CRYPTO_SDK-SERVER_API.md#13-multibaseutils) | | SignatureUtils | [Crypto SDK Server API - SignatureUtils](/docs/api/CRYPTO_SDK-SERVER_API.md#14-signatureutils) | ### CryptoUtils CryptoUtils provides features including ECC key pair generation and public key compression/decompression, nonce and salt generation, password-based key generation via PBKDF2, AES encryption/decryption, and SharedSecret generation.
The main features are as follows: * Create a key: Generate a key pair consisting of a public-private key pair. * Compress public keys: Compresses the public key into a byte array type. * Decompress public key: Decompress the compressed public key. * Generate a nonce: Generate a nonce. * Generate a salt: Generate a salt. * Create a SharedSecret: Create a SharedSecret. * Generate the PBKDF2 derived key: Generate an encryption key using the PBKDF2 algorithm for your wallet password. * Encrypt: Encrypt the data. * Decrypt: Decrypt the encrypted data. ### DigestUtils DigestUtils provides SHA hashing functionality.
The main features are as follows: * Hashification: Hash data using the SHA function. ### MultiBaseUtils MultiBaseUtils supports encoding/decoding functionality.
The main features are as follows: * encoding: Encodes the data. * decoding: Decode the data. ### SignatureUtils SignatureUtils provides signature functionality.
The main features are as follows: * Generate a signature: Signs the data using the ECDSA algorithm. * Generate compressed signature: Generate a compressed signature for the data. * Verify compressed signature: Verify the compressed signature.
## SDK Enumerator Enumerators used by OpenDID Server Crypto SDK.
The main features are as follows: * DidKeyType: Define the Did key type. * EccCurveType: Defines the Ecc Curve type. * EncryptionType: Define the encryption algorithm type. * EncryptionMode: Define the encryption mode type. * SymmetricKeySize: Define a key size type. * SymmetricPaddingType: Define the padding type. * SymmetricCipherType: Defines the type of symmetric key encryption algorithm. * DigestType: Define a digest type. * MultiBaseType: Define a multibase type. ================================================ FILE: source/did-crypto-sdk-server/README_ko.md ================================================ # Server Crypto SDK Guide 본 문서는 OpenDID Server Crypto SDK 사용을 위한 가이드로, Open DID에 필요한 암복호화를 Crypto, Degest, MultiBase, Signature Utils로서 기능을 제공한다. ## S/W 사양 | 구분 | 내용 | |------|----------------------------| | Language | Java 21| | Build System | Gradle 8.8 |
## 빌드 방법 : 본 SDK 프로젝트의 build.gradle 파일을 기반으로 JAR 파일을 생성한다. 1. 프로젝트의 `build.gradle` 파일을 열고 아래와 같은 구성파일의 태스크를 추가한다. ```groovy plugins { id 'java' } group = 'org.omnione.did' java { sourceCompatibility = '21' } jar { archiveBaseName.set('did-crypto-sdk-server') archiveVersion.set('2.0.0') archiveClassifier.set('') } repositories { mavenCentral() } dependencies { implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' } ``` 2. IDE에서 `Gradle` 창을 열고, 프로젝트의 `Tasks > build > clean & build` 태스크를 실행 또는 `./gradlew clean & build` 를 터미널 창에 입력한다. 3. 실행이 완료되면 `{projetPath}/build/libs/` 폴더에 `did-crypto-sdk-server-2.0.0.jar` 파일이 생성된다.
## SDK 적용 방법 1. 서버 프로젝트의 libs에 `did-crypto-sdk-server-2.0.0.jar` 파일을 복사한다. 2. 서버 프로젝트의 `build.gradle` 파일에 아래 의존성을 추가한다. ```groovy implementation files('libs/did-crypto-sdk-server-2.0.0.jar') implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' ``` 3. `Gradle`을 동기화하여 의존성이 제대로 추가되었는지 확인한다.
## API 규격서 | 구분 | API 문서 Link | |------|----------------------------| | CryptoUtils | [Crypto SDK Server API - CryptoUtils ](/docs/api/CRYPTO_SDK-SERVER_API_ko.md#11-cryptoutils) | | DigestUtils | [Crypto SDK Server API - DigestUtils ](/docs/api/CRYPTO_SDK-SERVER_API_ko.md#12-digestutils) | | MultiBaseUtils | [Crypto SDK Server API - MultiBaseUtils](/docs/api/CRYPTO_SDK-SERVER_API_ko.md#13-multibaseutils) | | SignatureUtils | [Crypto SDK Server API - SignatureUtils](/docs/api/CRYPTO_SDK-SERVER_API_ko.md#14-signatureutils) | ### CryptoUtils CryptoUtils는 ECC 키 쌍 생성 및 공개키 압축/해제, nonce 및 salt 생성, PBKDF2를 통한 패스워드 기반 키 생성, AES 암호화/복호화, 그리고 SharedSecret 생성을 포함한 기능을 제공한다.
주요 기능은 다음과 같다: * 키 생성: 공개키-개인키 쌍으로 이루어진 키페어를 생성한다. * 공개키 압축: 바이트 배열 타입으로 공개키를 압축한다. * 압축된 공개키 해제: 압축된 공개키를 해제한다. * nonce 생성: nonce 값을 생성한다. * salt 생성: salt 값을 생성한다. * SharedSecret 생성: SharedSecret을 생성한다. * pbkdf2 유도 키 생성: 월렛 패스워드를 PBKDF2 알고리즘을 사용한 암호화 키 생성 * 암호화: 데이터를 암호화한다. * 복호화: 암호화된 데이터를 복호화한다. ### DigestUtils DigestUtils는 SHA 해시 기능을 제공한다.
주요 기능은 다음과 같다: * 해시화: SHA 함수를 사용해 데이터 해시화를 한다. ### MultiBaseUtils MultiBaseUtils는 인코딩/디코딩 기능을 지원한다.
주요 기능은 다음과 같다: * 인코딩: 데이터를 인코딩한다. * 디코딩: 데이터를 디코딩한다. ### SignatureUtils SignatureUtils는 서명 기능을 제공한다.
주요 기능은 다음과 같다: * 서명값 생성: 데이터를 ECDSA 알고리즘을 사용해 서명한다. * 압축된 서명값 생성: 데이터를 압축된 서명값으로 생성한다. * 압축 서명값 검증: 압축된 서명값을 검증한다.
## SDK Enumerator OpenDID Server Crypto SDK 에서 사용하는 Enumerator
주요 기능은 다음과 같다: * DidKeyType: Did 키 타입을 정의한다. * EccCurveType: Ecc Curve 타입을 정의한다. * EncryptionType: 암호화 알고리즘 타입을 정의한다. * EncryptionMode: 암호화 Mode 타입을 정의한다. * SymmetricKeySize: 키 사이즈 타입을 정의한다. * SymmetricPaddingType: 패딩 타입을 정의한다. * SymmetricCipherType: 대칭키 암호화 알고리즘 타입을 정의한다. * DigestType: 다이제스트 타입을 정의한다. * MultiBaseType: 멀티베이스 타입을 정의한다. ================================================ FILE: source/did-crypto-sdk-server/build.gradle ================================================ plugins { id 'java' } group = 'org.omnione.did' java { sourceCompatibility = '21' } jar { archiveBaseName.set('did-crypto-sdk-server') archiveVersion.set('2.0.0') archiveClassifier.set('') } repositories { mavenCentral() } dependencies { implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' } ================================================ FILE: source/did-crypto-sdk-server/gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: source/did-crypto-sdk-server/gradlew ================================================ #!/bin/sh # # Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## # # Gradle start up script for POSIX generated by Gradle. # # Important for running: # # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is # noncompliant, but you have some other compliant shell such as ksh or # bash, then to run this script, type that shell name before the whole # command line, like: # # ksh Gradle # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», # «${var#prefix}», «${var%suffix}», and «$( cmd )»; # * compound commands having a testable exit status, especially «case»; # * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # # (2) This script targets any POSIX shell, so it avoids extensions provided # by Bash, Ksh, etc; in particular arrays are avoided. # # The "traditional" practice of packing multiple parameters into a # space-separated string is a well documented source of bugs and security # problems, so this is (mostly) avoided, by progressively accumulating # options in "$@", and eventually passing that to Java. # # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; # see the in-line comments for details. # # There are tweaks for specific operating systems such as AIX, CygWin, # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. # ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link app_path=$0 # Need this for daisy-chained symlinks. while APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path [ -h "$app_path" ] do ls=$( ls -ld "$app_path" ) link=${ls#*' -> '} case $link in #( /*) app_path=$link ;; #( *) app_path=$APP_HOME$link ;; esac done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum warn () { echo "$*" } >&2 die () { echo echo "$*" echo exit 1 } >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "$( uname )" in #( CYGWIN* ) cygwin=true ;; #( Darwin* ) darwin=true ;; #( MSYS* | MINGW* ) msys=true ;; #( NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD=$JAVA_HOME/jre/sh/java else JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD=java if ! command -v java >/dev/null 2>&1 then die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi # Collect all arguments for the java command, stacking in reverse order: # * args from the command line # * the main class name # * -classpath # * -D...appname settings # * --module-path (only if needed) # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) # Now convert the arguments - kludge to limit ourselves to /bin/sh for arg do if case $arg in #( -*) false ;; # don't mess with options #( /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath [ -e "$t" ] ;; #( *) false ;; esac then arg=$( cygpath --path --ignore --mixed "$arg" ) fi # Roll the args list around exactly as many times as the number of # args, so each arg winds up back in the position where it started, but # possibly modified. # # NB: a `for` loop captures its iteration list before it begins, so # changing the positional parameters here affects neither the number of # iterations, nor the values presented in `arg`. shift # remove old arg set -- "$@" "$arg" # push replacement arg done fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ org.gradle.wrapper.GradleWrapperMain \ "$@" # Stop when "xargs" is not available. if ! command -v xargs >/dev/null 2>&1 then die "xargs is not available" fi # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. # # In Bash we could simply go: # # readarray ARGS < <( xargs -n1 <<<"$var" ) && # set -- "${ARGS[@]}" "$@" # # but POSIX shell has neither arrays nor command substitution, so instead we # post-process each arg (as a line of input to sed) to backslash-escape any # character that might be a shell metacharacter, then use eval to reverse # that process (while maintaining the separation between arguments), and wrap # the whole thing up as a single "set" statement. # # This will of course break if any of these variables contains a newline or # an unmatched quote. # eval "set -- $( printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | xargs -n1 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | tr '\n' ' ' )" '"$@"' exec "$JAVACMD" "$@" ================================================ FILE: source/did-crypto-sdk-server/gradlew.bat ================================================ @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Resolve any "." and ".." in APP_HOME to make it shorter. for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute echo. 1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute echo. 1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 goto fail :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! set EXIT_CODE=%ERRORLEVEL% if %EXIT_CODE% equ 0 set EXIT_CODE=1 if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: source/did-crypto-sdk-server/settings.gradle ================================================ rootProject.name = 'did-crypto-sdk-server' ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/constant/CryptoConstant.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.constant; public class CryptoConstant { public static final String PROVIDER_BC = "BC"; public static final String PROVIDER_EC = "EC"; public static final String ALG_NONCE = "SHA1PRNG"; public static final String ALG_RSA = "RSA"; public static final String ALG_AES = "AES"; public static final String SIG_ALG_SHA256_RSA = "SHA256withRSA"; public static final String SIG_ALG_SHA256_ECDSA = "SHA256withECDSA"; public static final String SIG_ALG_NONE_ECDSA = "NoneWithECDSA"; public static final String PBKDF2_ALG_HMAC_SHA1 = "PBKDF2WithHmacSHA1"; public static final String HASH_ALG_SHA256 = "SHA-256"; public static final String HASH_ALG_SHA384 = "SHA-384"; public static final String HASH_ALG_SHA512 = "SHA-512"; } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/ec/CompactSign.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.ec; import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.Arrays; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.x9.X9IntegerConverter; import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.math.ec.ECAlgorithms; import org.bouncycastle.math.ec.ECPoint; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; public class CompactSign { /** * Converts an ECDSA signature in ASN.1 DER format to a compact signature. * * @param compressedPubKey The compressed public key used for recovery ID calculation * @param hashedsource The hashed original data * @param signData The ECDSA signature in ASN.1 DER format * @param curveName The name of the elliptic curve used * @return The compact signature * @throws CryptoException */ public byte[] getSignBytes(byte[] compressedPubKey, byte[] hashedsource, byte[] signData, String curveName) throws CryptoException { ASN1Sequence asn1Sequence = parseASN1Sequence(signData); BigInteger[] rs = extractRS(asn1Sequence); BigInteger integerR = rs[0]; BigInteger integerS = adjustS(rs[1], curveName); byte[] r = padTo32Bytes(integerR); byte[] s = padTo32Bytes(integerS); byte recoveryId = getRecoveryId(r, s, hashedsource, compressedPubKey, curveName); if (recoveryId < 0) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_RECOVERY_ID); } return buildSignature(recoveryId, r, s); } /** * Parses the ASN.1 DER encoded signature data. * * @param signData The ECDSA signature in ASN.1 DER format * @return The ASN1Sequence containing the R and S values * @throws CryptoException */ private ASN1Sequence parseASN1Sequence(byte[] signData) throws CryptoException { try (ByteArrayInputStream inStream = new ByteArrayInputStream(signData); ASN1InputStream asnInputStream = new ASN1InputStream(inStream)) { ASN1Primitive asn1 = asnInputStream.readObject(); if (!(asn1 instanceof ASN1Sequence)) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_ASN1_SEQUENCE); } return (ASN1Sequence) asn1; } catch (IOException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_ASN1_SEQUENCE, e); } } /** * Extracts the R and S values from the ASN.1 sequence. * * @param asn1Sequence The ASN1Sequence containing the R and S values * @return an array of BigIntegers containing the R and S values * @throws CryptoException */ private BigInteger[] extractRS(ASN1Sequence asn1Sequence) throws CryptoException { ASN1Encodable[] asn1Encodables = asn1Sequence.toArray(); if (asn1Encodables.length != 2) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_SIGN_VALUE); } BigInteger integerR = ((ASN1Integer) asn1Encodables[0].toASN1Primitive()).getValue(); BigInteger integerS = ((ASN1Integer) asn1Encodables[1].toASN1Primitive()).getValue(); return new BigInteger[]{integerR, integerS}; } /** * Adjusts the S value to ensure it is less than or equal to half the curve order. * * @param s The original S value * @param curveName The name of the elliptic curve used * @return The adjusted S value */ private BigInteger adjustS(BigInteger s, String curveName) { BigInteger curveN = CustomNamedCurves.getByName(curveName).getN(); BigInteger halfCurveOrder = curveN.shiftRight(1); if (s.compareTo(halfCurveOrder) > 0) { s = curveN.subtract(s); } return s; } /** * Pads the BigInteger to a 32-byte array. * * @param value The BigInteger value to pad * @return The padded 32-byte array */ private byte[] padTo32Bytes(BigInteger value) { byte[] result = new byte[32]; byte[] byteArray = value.toByteArray(); if (byteArray.length > 32) { System.arraycopy(byteArray, byteArray.length - 32, result, 0, 32); } else if (byteArray.length < 32) { System.arraycopy(byteArray, 0, result, 32 - byteArray.length, byteArray.length); } else { result = byteArray; } return result; } /** * Calculates the recovery ID for the given R and S values and the hashed message. * * @param sigR The R value of the signature * @param sigS The S value of the signature * @param hassedMessage The hashed original data * @param publicKey The compressed public key used for recovery ID calculation * @param curveName The name of the elliptic curve used * @return The recovery ID * @throws CryptoException */ private byte getRecoveryId(byte[] sigR, byte[] sigS, byte[] hassedMessage, byte[] publicKey, String curveName) throws CryptoException { ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curveName); BigInteger pointN = spec.getN(); for (int recoveryId = 0; recoveryId < 2; recoveryId++) { try { BigInteger pointX = new BigInteger(1, sigR); ECPoint pointR = decodePoint(spec, pointX, recoveryId); if (!pointR.multiply(pointN).isInfinity()) { continue; } ECPoint pointQ = recoverPublicKey(spec, pointR, new BigInteger(1, sigS), new BigInteger(1, hassedMessage)); if (Arrays.equals(publicKey, pointQ.getEncoded(true))) { return (byte) recoveryId; } } catch (RuntimeException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_RECOVERY_ID, e.getMessage()); } } throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_RECOVERY_ID); } /** * Decodes the ECPoint from the given point X and recovery ID. * * @param spec The elliptic curve parameter specification * @param pointX The X coordinate of the point * @param recoveryId The recovery ID * @return The decoded ECPoint */ private static ECPoint decodePoint(ECNamedCurveParameterSpec spec, BigInteger pointX, int recoveryId) { X9IntegerConverter x9 = new X9IntegerConverter(); byte[] compEnc = x9.integerToBytes(pointX, 1 + x9.getByteLength(spec.getCurve())); compEnc[0] = (byte) ((recoveryId & 1) == 1 ? 0x03 : 0x02); return spec.getCurve().decodePoint(compEnc); } /** * Recovers the public key from the given parameters. * * @param spec The elliptic curve parameter specification * @param pointR The R point of the signature * @param sigS The S value of the signature * @param message Hashed original data converted to BigInteger * @return The recovered public key */ private ECPoint recoverPublicKey(ECNamedCurveParameterSpec spec, ECPoint pointR, BigInteger sigS, BigInteger message) { BigInteger pointN = spec.getN(); BigInteger pointEInv = message.negate().mod(pointN); BigInteger pointRInv = pointR.getXCoord().toBigInteger().modInverse(pointN); BigInteger srInv = pointRInv.multiply(sigS).mod(pointN); BigInteger pointEInvRInv = pointRInv.multiply(pointEInv).mod(pointN); return ECAlgorithms.sumOfTwoMultiplies(spec.getG(), pointEInvRInv, pointR, srInv); } /** * Builds the compact signature from the given recovery ID, R and S values. * * @param recoveryId The recovery ID * @param r The R value of the signature * @param s The S value of the signature * @return The compact signature */ private byte[] buildSignature(byte recoveryId, byte[] r, byte[] s) { byte[] combined = new byte[65]; ByteBuffer buff = ByteBuffer.wrap(combined); buff.put((byte) (recoveryId + 27 + 4)); buff.put(r); buff.put(s); return combined; } /** * Verifies the compact signature with the compressed public key. * * @param pubkey_rw the compressed public key * @param hashedSource The hashed original data * @param signature_rw The compact signature * @param curveName The name of the elliptic curve used * @throws CryptoException */ public void verifySign(byte[] pubkey_rw, byte[] hashedSource, byte[] signature_rw, String curveName) throws CryptoException { if (pubkey_rw.length != 33) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PUBLIC_KEY); } if (signature_rw == null || signature_rw.length != 65) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_SIGN_VALUE); } byte[] sigR = Arrays.copyOfRange(signature_rw, 1, 33); byte[] sigS = Arrays.copyOfRange(signature_rw, 33, 65); int recId = (signature_rw[0] & 0xFF) - 27 - 4; byte[] recoveredPubKey = getRecoveryComPublicKey(sigR, sigS, hashedSource, curveName, recId); if (!Arrays.equals(pubkey_rw, recoveredPubKey)) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_NO_MATCH_RECOVERY_KEY); } } /** * Recovers the compressed public key from the given signature components (R, S) and hashed source data. * * @param sigR The R component of the ECDSA signature. * @param sigS The S component of the ECDSA signature. * @param hashedSource The hashed original data that was signed. * @param curveName The name of the elliptic curve used for the ECDSA signature. * @param recoveryId The recovery ID used to reconstruct the public key. * @return The compressed public key as a byte array. * @throws CryptoException */ private static byte[] getRecoveryComPublicKey(byte[] sigR, byte[] sigS, byte[] hashedSource, String curveName, int recoveryId) throws CryptoException { ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curveName); BigInteger pointN = spec.getN(); try { BigInteger pointX = new BigInteger(1, sigR); ECPoint pointR = decodePoint(spec, pointX, recoveryId); BigInteger pointEInv = new BigInteger(1, hashedSource).negate().mod(pointN); BigInteger pointRInv = pointR.getXCoord().toBigInteger().modInverse(pointN); BigInteger srInv = pointRInv.multiply(new BigInteger(1, sigS)).mod(pointN); BigInteger pointEInvRInv = pointRInv.multiply(pointEInv).mod(pointN); ECPoint pointQ = ECAlgorithms.sumOfTwoMultiplies(spec.getG(), pointEInvRInv, pointR, srInv); return pointQ.getEncoded(true); } catch (RuntimeException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_PUBLIC_KEY_RECOVERY_FAIL, e.getMessage()); } } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/encoding/Base58.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.encoding; import java.nio.charset.StandardCharsets; public class Base58 { private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); private static final int[] INDEXES = new int[128]; static { for (int i = 0; i < INDEXES.length; i++) { INDEXES[i] = -1; } for (int i = 0; i < ALPHABET.length; i++) { INDEXES[ALPHABET[i]] = i; } } /** * Encodes the given byte array using Base58 encoding. * * @param input the byte array to encode * @return the Base58 encoded string */ public static String encode(byte[] input) { if (input.length == 0) { return ""; } input = copyOfRange(input, 0, input.length); int zeroCount = 0; while (zeroCount < input.length && input[zeroCount] == 0) { zeroCount++; } byte[] temp = new byte[input.length * 2]; int j = temp.length; int startAt = zeroCount; while (startAt < input.length) { byte mod = divmod(input, startAt, 58); if (input[startAt] == 0) { startAt++; } temp[--j] = (byte) ALPHABET[mod]; } while (j < temp.length && temp[j] == ALPHABET[0]) { j++; } while (zeroCount-- > 0) { temp[--j] = (byte) ALPHABET[0]; } return new String(temp, j, temp.length - j, StandardCharsets.US_ASCII); } /** * Decodes the given Base58 encoded string into a byte array. * * @param input the Base58 encoded string to decode * @return the decoded byte array, or null if the input is not valid Base58 */ public static byte[] decode(String input) { if (input.length() == 0) { return new byte[0]; } byte[] input58 = new byte[input.length()]; for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); int digit58 = (c < 128) ? INDEXES[c] : -1; if (digit58 < 0) { return null; } input58[i] = (byte) digit58; } int zeroCount = 0; while (zeroCount < input58.length && input58[zeroCount] == 0) { zeroCount++; } byte[] temp = new byte[input.length()]; int j = temp.length; int startAt = zeroCount; while (startAt < input58.length) { byte mod = divmod(input58, startAt, 256); if (input58[startAt] == 0) { startAt++; } temp[--j] = mod; } while (j < temp.length && temp[j] == 0) { j++; } return copyOfRange(temp, j - zeroCount, temp.length); } /** * Performs division and modulo operations on the given byte array. * * @param number the byte array to operate on * @param startAt the starting index for the operation * @param base the base to use for the division and modulo operations * @return the remainder of the division operation */ private static byte divmod(byte[] number, int startAt, int base) { int remainder = 0; for (int i = startAt; i < number.length; i++) { int digit = (number[i] & 0xFF); int temp = (base == 58 ? remainder * 256 : remainder * 58) + digit; number[i] = (byte) (temp / base); remainder = temp % base; } return (byte) remainder; } /** * Copies a range of elements from the given byte array. * * @param source the source byte array * @param from the starting index (inclusive) * @param to the ending index (exclusive) * @return the new byte array containing the specified range from the source array */ private static byte[] copyOfRange(byte[] source, int from, int to) { byte[] range = new byte[to - from]; System.arraycopy(source, from, range, 0, range.length); return range; } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/engines/AesEngine.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.engines; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.omnione.did.crypto.enums.EncryptionMode; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; public class AesEngine { /** * Encrypts or decrypts data using the specified AES cipher information, key, and IV. * * @param source the data to be encrypted or decrypted * @param cipherInfo The cipher information (e.g., algorithm, mode, padding) * @param key the encryption key * @param iv the initialization vector (IV) * @param mode the operation mode (Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE) * @return the encrypted or decrypted data * @throws CryptoException */ public byte[] aesEncryptDecrypt(byte[] source, CipherInfo cipherInfo, byte[] key, byte[] iv, int mode) throws CryptoException { byte[] encDecData = null; SecretKey sKey = new SecretKeySpec(key, 0, key.length, cipherInfo.getType().getRawValue()); AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv); Cipher cipher; try { cipher = Cipher.getInstance(convertCipherType(cipherInfo)); if(EncryptionMode.ECB == cipherInfo.getMode()) { cipher.init(mode, sKey); } else { cipher.init(mode, sKey, ivSpec); } encDecData = cipher.doFinal(source); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_ENCDEC_FAIL, e.getMessage()); } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_ENCDEC_FAIL, e.getMessage()); } catch (IllegalBlockSizeException | BadPaddingException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_ENCDEC_FAIL, e.getMessage()); } return encDecData; } /** * Converts the cipher information to a string format used by the Cipher class. * * @param cipherInfo The cipher information (e.g., algorithm, mode, padding) * @return The string representation of the cipher information */ private String convertCipherType(CipherInfo cipherInfo) { StringBuilder sb = new StringBuilder(); sb.append(cipherInfo.getType().getRawValue()); sb.append("/"); sb.append(cipherInfo.getMode().getRawValue()); sb.append("/"); sb.append(cipherInfo.getPadding().getRawValue()); return sb.toString(); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/engines/CipherInfo.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.engines; import org.omnione.did.crypto.enums.EncryptionMode; import org.omnione.did.crypto.enums.EncryptionType; import org.omnione.did.crypto.enums.SymmetricCipherType; import org.omnione.did.crypto.enums.SymmetricKeySize; import org.omnione.did.crypto.enums.SymmetricPaddingType; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; public class CipherInfo { /** * The type of encryption algorithm enum (e.g., AES). */ private EncryptionType type; /** * The mode of operation for the cipher (e.g., CBC, ECB). */ private EncryptionMode mode; /** * The size of the symmetric key (e.g., 128 bits, 256 bits). */ private SymmetricKeySize size; /** * The padding type used in the cipher (e.g., PKCS7). */ private SymmetricPaddingType padding; public CipherInfo() { this.type = EncryptionType.AES; this.mode = EncryptionMode.CBC; this.size = SymmetricKeySize.Size256; this.padding = SymmetricPaddingType.PKCS5; } public CipherInfo(EncryptionType type, EncryptionMode mode, SymmetricKeySize size, SymmetricPaddingType padding) { this.type = type; this.mode = mode; this.size = size; this.padding = padding; } /** * Constructs a CipherInfo object with the specified cipher type and padding type. * * @param cipherType The type of symmetric cipher. * @param paddingType The type of padding used in the cipher. * @throws CryptoException */ public CipherInfo(SymmetricCipherType cipherType, SymmetricPaddingType paddingType) throws CryptoException { this.padding = paddingType; switch(cipherType) { case AES_128_CBC : this.type = EncryptionType.AES; this.mode = EncryptionMode.CBC; this.size = SymmetricKeySize.Size128; break; case AES_128_ECB : this.type = EncryptionType.AES; this.mode = EncryptionMode.ECB; this.size = SymmetricKeySize.Size128; break; case AES_256_CBC : this.type = EncryptionType.AES; this.mode = EncryptionMode.CBC; this.size = SymmetricKeySize.Size256; break; case AES_256_ECB : this.type = EncryptionType.AES; this.mode = EncryptionMode.ECB; this.size = SymmetricKeySize.Size256; break; default: throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_INVALID_CIPHER_INFO_TYPE); } } public EncryptionType getType() { return type; } public void setType(EncryptionType type) { this.type = type; } public EncryptionMode getMode() { return mode; } public void setMode(EncryptionMode mode) { this.mode = mode; } public SymmetricKeySize getSize() { return size; } public void setSize(SymmetricKeySize size) { this.size = size; } public SymmetricPaddingType getPadding() { return padding; } public void setPadding(SymmetricPaddingType padding) { this.padding = padding; } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/enums/DidKeyType.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.enums; import java.util.EnumSet; public enum DidKeyType { RSA_VERIFICATION_KEY_2018("RsaVerificationKey2018"), SECP256K1_VERIFICATION_KEY_2018("Secp256k1VerificationKey2018"), SECP256R1_VERIFICATION_KEY_2018("Secp256r1VerificationKey2018"); private String rawValue; DidKeyType(String rawValue) { this.rawValue = rawValue; } public String getRawValue() { return rawValue; } public static DidKeyType fromString(String rawValue) { for (DidKeyType b : DidKeyType.values()) { if (b.rawValue.equalsIgnoreCase(rawValue)) { return b; } } return null; } public static EnumSet all() { return EnumSet.allOf(DidKeyType.class); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/enums/DigestType.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.enums; import java.util.EnumSet; public enum DigestType { SHA256("sha256"), SHA512("sha512"), SHA384("sha384"); private String rawValue; DigestType(String rawValue) { this.rawValue = rawValue; } public String getRawValue() { return rawValue; } // default Sha384 or null .. public static DigestType fromString(String text) { for (DigestType b : DigestType.values()) { if (b.rawValue.equalsIgnoreCase(text)) { return b; } } return SHA384; } public static EnumSet all() { return EnumSet.allOf(DigestType.class); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/enums/EccCurveType.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.enums; import java.util.EnumSet; public enum EccCurveType { Secp256k1("Secp256k1"), Secp256r1("Secp256r1"); EccCurveType(String curveName) { this.curveName = curveName; } private String curveName; public String getCurveName() { return curveName; } public static EccCurveType fromString(String text) { for (EccCurveType b : EccCurveType.values()) { if (b.curveName.equalsIgnoreCase(text)) { return b; } } return null; } public static EnumSet all() { return EnumSet.allOf(EccCurveType.class); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/enums/EncryptionMode.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.enums; import java.util.EnumSet; public enum EncryptionMode { CBC("CBC"), ECB("ECB"); private String rawValue; public String getRawValue() { return rawValue; } public void setRawValue(String mode) { this.rawValue = mode; } EncryptionMode(String mode) { this.rawValue = mode; } public static EncryptionMode fromString(String text) { for (EncryptionMode b : EncryptionMode.values()) { if (b.rawValue.equalsIgnoreCase(text)) { return b; } } return null; } public static EnumSet all() { return EnumSet.allOf(EncryptionMode.class); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/enums/EncryptionType.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.enums; import java.util.EnumSet; public enum EncryptionType { AES("AES"); private String rawValue; EncryptionType(String encType) { this.setRawValue(encType); } public String getRawValue() { return rawValue; } public void setRawValue(String encType) { this.rawValue = encType; } public static EncryptionType fromString(String text) { for (EncryptionType b : EncryptionType.values()) { if (b.rawValue.equalsIgnoreCase(text)) { return b; } } return null; } public static EnumSet all() { return EnumSet.allOf(EncryptionType.class); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/enums/MultiBaseType.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.enums; import java.util.EnumSet; public enum MultiBaseType { base16("f"), base16upper("F"), base58btc("z"), base64url("u"), base64("m"); private String character; MultiBaseType(String character) { this.character = character.substring(0, 1); } public String getCharacter() { return character; } public static MultiBaseType getByCharacter(String inputCharacter) { for (MultiBaseType value : MultiBaseType.values()) { if (value.character.equalsIgnoreCase(inputCharacter)) { return value; } } // If there is no matching value for the input character, Base64url is returned as the default value. return base64url; } public static EnumSet all() { return EnumSet.allOf(MultiBaseType.class); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/enums/SymmetricCipherType.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.enums; import java.util.EnumSet; public enum SymmetricCipherType { AES_128_CBC("AES-128-CBC"), AES_128_ECB("AES-128-ECB"), AES_256_CBC("AES-256-CBC"), AES_256_ECB("AES-256-ECB"); private String rawValue; SymmetricCipherType(String rawValue) { this.rawValue = rawValue; } public String getRawValue() { return rawValue; } public static SymmetricCipherType fromString(String text) { for (SymmetricCipherType b : SymmetricCipherType.values()) { if (b.rawValue.equalsIgnoreCase(text)) { return b; } } return null; } public static EnumSet all() { return EnumSet.allOf(SymmetricCipherType.class); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/enums/SymmetricKeySize.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.enums; import java.util.EnumSet; public enum SymmetricKeySize { Size128(128), Size256(256); private int rawValue; SymmetricKeySize(int size) { this.setRawValue(size); } public int getRawValue() { return rawValue; } public void setRawValue(int size) { this.rawValue = size; } public static SymmetricKeySize fromString(int value) { for (SymmetricKeySize b : SymmetricKeySize.values()) { if (b.rawValue == value) { return b; } } return null; } public static EnumSet all() { return EnumSet.allOf(SymmetricKeySize.class); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/enums/SymmetricPaddingType.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.enums; import java.util.EnumSet; public enum SymmetricPaddingType { NOPAD("NoPadding"), PKCS5("PKCS5Padding"); private String rawValue; public String getRawValue() { return rawValue; } public void setRawValue(String padding) { this.rawValue = padding; } SymmetricPaddingType(String padding) { this.rawValue = padding; } public static SymmetricPaddingType fromString(String rawValue) { for (SymmetricPaddingType type : SymmetricPaddingType.values()) { if (type.getRawValue().equals(rawValue)) { return type; } } throw new IllegalArgumentException("No enum constant with rawValue " + rawValue); } public static EnumSet all() { return EnumSet.allOf(SymmetricPaddingType.class); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/exception/CryptoErrorCode.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.exception; public enum CryptoErrorCode implements CryptoErrorCodeInterface{ ERR_CODE_CRYPTO_SDK_BASE("SSDKCRT", ""), ERR_CODE_DIGESTUTIL_BASE(ERR_CODE_CRYPTO_SDK_BASE, "01", ""), ERR_CODE_DIGESTUTIL_INVALID_HASH_TYPE(ERR_CODE_DIGESTUTIL_BASE, "000", "Hash type is invalid"), ERR_CODE_DIGESTUTIL_GEN_HASH_FAIL(ERR_CODE_DIGESTUTIL_BASE, "001", "Failed to generate hash"), ERR_CODE_DIGESTUTIL_GEN_RANDOM_FAIL(ERR_CODE_DIGESTUTIL_BASE, "002", "Failed to generate secure random"), ERR_CODE_DIGESTUTIL_HASH_TYPE_OR_SOURCE_IS_NULL(ERR_CODE_DIGESTUTIL_BASE, "003", "Hash type or Source is null"), ERR_CODE_CRYPTOUTIL_BASE(ERR_CODE_CRYPTO_SDK_BASE, "02", ""), ERR_CODE_CRYPTOUTIL_INVALID_DID_KEY_TYPE(ERR_CODE_CRYPTOUTIL_BASE, "000", "Invalid DID Key Type"), ERR_CODE_CRYPTOUTIL_GEN_RANDOM_KEY_FAIL(ERR_CODE_CRYPTOUTIL_BASE, "001", "Failed to generate random key"), ERR_CODE_CRYPTOUTIL_COMPRESS_PUBLIC_KEY_FAIL(ERR_CODE_CRYPTOUTIL_BASE, "002", "Failed to Compress PublicKey"), ERR_CODE_CRYPTOUTIL_UNCOMPRESS_PUBLIC_KEY_FAIL(ERR_CODE_CRYPTOUTIL_BASE, "003", "Failed to UnCompress PublicKey"), ERR_CODE_CRYPTOUTIL_GEN_SECRET_FAIL(ERR_CODE_CRYPTOUTIL_BASE, "004", "Failed to generate shared secret"), ERR_CODE_CRYPTOUTIL_INVALID_CIPHER_INFO_TYPE(ERR_CODE_CRYPTOUTIL_BASE, "005", "Cipher type is invalid"), ERR_CODE_CRYPTOUTIL_ENCDEC_FAIL(ERR_CODE_CRYPTOUTIL_BASE, "006", "Failed to Encrypt, Decrypt"), ERR_CODE_CRYPTOUTIL_CONVERT_RSA_KEY_FAIL(ERR_CODE_CRYPTOUTIL_BASE, "007", "Failed to convert Rsa Key"), ERR_CODE_MULTIBASEUTIL_BASE(ERR_CODE_CRYPTO_SDK_BASE, "03", ""), ERR_CODE_MULTIBASEUTIL_INVALID_ENCODING_TYPE(ERR_CODE_MULTIBASEUTIL_BASE, "000", "Multibase encoding type is invalid"), ERR_CODE_MULTIBASEUTIL_INVALID_DECODING_TYPE(ERR_CODE_MULTIBASEUTIL_BASE, "001", "Multibase decoding type is invalid"), ERR_CODE_SIGNATUREUTIL_BASE(ERR_CODE_CRYPTO_SDK_BASE, "04", ""), ERR_CODE_SIGNATUREUTIL_INVALID_RECOVERY_ID(ERR_CODE_SIGNATUREUTIL_BASE, "000", "Failed to recover valid recovery ID"), ERR_CODE_SIGNATUREUTIL_INVALID_PARAM(ERR_CODE_MULTIBASEUTIL_BASE, "001", "The provided input value is invalid."), ERR_CODE_SIGNATUREUTIL_INVALID_ASN1_SEQUENCE(ERR_CODE_SIGNATUREUTIL_BASE, "002", "This indicates that the ASN.1 sequence is invalid"), ERR_CODE_SIGNATUREUTIL_INVALID_SIGN_VALUE(ERR_CODE_SIGNATUREUTIL_BASE, "003", "It is not a compact sign"), ERR_CODE_SIGNATUREUTIL_INVALID_PUBLIC_KEY(ERR_CODE_SIGNATUREUTIL_BASE, "004", "The publicKey is not in compressed public key format"), ERR_CODE_SIGNATUREUTIL_PUBLIC_KEY_RECOVERY_FAIL(ERR_CODE_SIGNATUREUTIL_BASE, "005", "RecoveryKey creation failed"), ERR_CODE_SIGNATUREUTIL_NO_MATCH_RECOVERY_KEY(ERR_CODE_SIGNATUREUTIL_BASE, "006", "RecoveryKey and publicKey do not match"), ; private String code; private String msg; private CryptoErrorCode(String code, String msg) { this.code = code; this.msg = msg; } private CryptoErrorCode(CryptoErrorCode errCodeKeymanagerKeyBase, String code, String msg) { this.code = errCodeKeymanagerKeyBase.getCode() + code; this.msg = msg; } @Override public String getCode() { return code; } @Override public String getMsg() { return msg; } public static CryptoErrorCodeInterface getEnumByCode(String code) { CryptoErrorCode agentTypes[] = CryptoErrorCode.values(); for (CryptoErrorCode iwCode : agentTypes) { if(iwCode.getCode() == code){ return iwCode; } } throw new AssertionError("Unknown Enum Code"); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/exception/CryptoErrorCodeInterface.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.exception; public interface CryptoErrorCodeInterface { public String getMsg(); public String getCode(); } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/exception/CryptoException.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.exception; public class CryptoException extends Exception{ /** * */ private static final long serialVersionUID = 6285544788893947401L; /** * Error Code - Use the int range */ protected String errorCode; /** * Error code message */ protected String errorMsg; /** * Error reason */ protected String errorReason; public CryptoException(CryptoErrorCodeInterface ErrorEnum) { super("ErrorCode: " + ErrorEnum.getCode() + ", Message: " + ErrorEnum.getMsg()); this.errorCode = ErrorEnum.getCode(); this.errorMsg = ErrorEnum.getMsg(); } public CryptoException(CryptoErrorCodeInterface ErrorEnum, String errorReason) { super("ErrorCode: " + ErrorEnum.getCode() + ", Message: " + ErrorEnum.getMsg() + ", Reason: " + errorReason); this.errorCode = ErrorEnum.getCode(); this.errorMsg = ErrorEnum.getMsg(); this.errorReason = errorReason; } public CryptoException(String errorCode, String errorMsg) { super("ErrorCode: " + errorCode + ", Message: " + errorMsg); this.errorCode = errorCode; this.errorMsg = errorMsg; } public CryptoException(String iwErrorCode, Throwable throwable) { super(iwErrorCode, throwable); } public CryptoException(String errorCode, String errorMsg, String errorReason) { super("ErrorCode: " + errorCode + ", Message: " + errorMsg + ", Reason: " + errorReason); this.errorCode = errorCode; this.errorMsg = errorMsg; this.errorReason = errorReason; } public CryptoException(CryptoErrorCode errorCode, Throwable throwable) { super("ErrorCode: " + errorCode + ", Reason: " + throwable); this.errorCode = errorCode.getCode(); this.errorMsg = errorCode.getMsg(); } public String getErrorCode() { return errorCode; } public String getErrorReason() { return errorReason; } public String getErrorMsg() { return errorMsg; } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/generator/EcKeyPairGenerator.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.generator; import java.security.InvalidAlgorithmParameterException; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.spec.ECParameterSpec; import org.omnione.did.crypto.constant.CryptoConstant; import org.omnione.did.crypto.enums.EccCurveType; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; import org.omnione.did.crypto.keypair.EcKeyPair; import org.omnione.did.crypto.keypair.KeyPairInterface; public class EcKeyPairGenerator { /** * Generates an EC key pair using the specified ECC curve type. * * @param eccCurveType The type of ECC curve to use * @return The generated EC key pair * @throws CryptoException */ public KeyPairInterface generateKeyPair(EccCurveType eccCurveType) throws CryptoException { EcKeyPair ecKeyPair; try { KeyPairGenerator g = KeyPairGenerator.getInstance(CryptoConstant.PROVIDER_EC, CryptoConstant.PROVIDER_BC); ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(eccCurveType.getCurveName()); g.initialize(ecSpec); java.security.KeyPair keyPair = g.generateKeyPair(); ecKeyPair = new EcKeyPair(keyPair.getPublic(), keyPair.getPrivate()); ecKeyPair.setECType(eccCurveType); } catch (NoSuchAlgorithmException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_GEN_RANDOM_KEY_FAIL, e.getMessage()); } catch (NoSuchProviderException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_GEN_RANDOM_KEY_FAIL, e.getMessage()); } catch (InvalidAlgorithmParameterException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_GEN_RANDOM_KEY_FAIL, e.getMessage()); } return ecKeyPair; } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/generator/GenerateSecureRandom.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.generator; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import org.omnione.did.crypto.constant.CryptoConstant; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; public class GenerateSecureRandom { private static int DEFAULT_KEYSIZE = 256; private static int DEFAULT_SALTLENGTH = DEFAULT_KEYSIZE / 8; private static int DEFAULT_NONCELENGTH = 16; public byte[] generateNonce() throws CryptoException { return generateSecureRandom(DEFAULT_NONCELENGTH); } public byte[] generateSalt() throws CryptoException { return generateSecureRandom(DEFAULT_SALTLENGTH); } public byte[] generateSecureRandom(int size) throws CryptoException { try { SecureRandom random; random = SecureRandom.getInstance(CryptoConstant.ALG_NONCE); byte bytes[] = new byte[size]; random.nextBytes(bytes); return bytes; } catch (NoSuchAlgorithmException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_DIGESTUTIL_GEN_RANDOM_FAIL, e.getMessage()); } } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/generator/RsaKeyPairGenerator.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.generator; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import org.omnione.did.crypto.constant.CryptoConstant; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; import org.omnione.did.crypto.keypair.KeyPairInterface; import org.omnione.did.crypto.keypair.RsaKeyPair; public class RsaKeyPairGenerator { public KeyPairInterface generateKeyPair() throws CryptoException { KeyPairGenerator keyGen; java.security.KeyPair key = null; try { keyGen = KeyPairGenerator.getInstance(CryptoConstant.ALG_RSA); keyGen.initialize(2048); key = keyGen.generateKeyPair(); } catch (NoSuchAlgorithmException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_GEN_RANDOM_KEY_FAIL, e.getMessage()); } RsaKeyPair rsaKeyPair = new RsaKeyPair(); rsaKeyPair.setPrivateKey(key.getPrivate()); rsaKeyPair.setPublicKey(key.getPublic()); return rsaKeyPair; } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/keypair/EcKeyPair.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.keypair; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import org.omnione.did.crypto.enums.EccCurveType; import org.omnione.did.crypto.enums.MultiBaseType; import org.omnione.did.crypto.exception.CryptoException; import org.omnione.did.crypto.util.CryptoUtils; import org.omnione.did.crypto.util.MultiBaseUtils; public class EcKeyPair implements KeyPairInterface{ /** * The elliptic curve type associated with this key pair. */ EccCurveType eccCurveType; /** * The elliptic curve public key. */ private PublicKey publicKey; /** * The elliptic curve private key. */ private PrivateKey privateKey; public EcKeyPair(PublicKey publicKey, PrivateKey privateKey) { this.publicKey = (PublicKey) publicKey; this.privateKey = (PrivateKey) privateKey; } @Override public PublicKey getPublicKey() { return publicKey; } @Override public void setPublicKey(PublicKey publicKey) { this.publicKey = (ECPublicKey) publicKey; } @Override public PrivateKey getPrivateKey() { return privateKey; } @Override public void setPrivateKey(PrivateKey privateKey) { this.privateKey = (ECPrivateKey) privateKey; } public void setECType(EccCurveType eccCurveType) { this.eccCurveType = eccCurveType; } public EccCurveType getECType() { return eccCurveType; } public String getBase58PubKey() throws CryptoException { return MultiBaseUtils.encode(publicKey.getEncoded(), MultiBaseType.base58btc); } public String getBase58CompreessPubKey() throws CryptoException { byte[] compressPublicKey = CryptoUtils.compressPublicKey(publicKey.getEncoded(), eccCurveType); return MultiBaseUtils.encode(compressPublicKey, MultiBaseType.base58btc); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/keypair/KeyPairInterface.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.keypair; import java.security.PrivateKey; import java.security.PublicKey; public interface KeyPairInterface { /** * Returns the public key of the key pair. * * @return the public key. */ public PublicKey getPublicKey(); /** * Sets the public key of the key pair. * * @param publicKey the public key to set. */ public void setPublicKey(PublicKey publicKey); /** * Returns the private key of the key pair. * * @return the private key. */ public PrivateKey getPrivateKey(); /** * Sets the private key of the key pair. * * @param privateKey the private key to set. */ public void setPrivateKey(PrivateKey privateKey); } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/keypair/RsaKeyPair.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.keypair; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import org.omnione.did.crypto.constant.CryptoConstant; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; public class RsaKeyPair implements KeyPairInterface{ private PrivateKey privateKey; private PublicKey publicKey; public RsaKeyPair() { super(); } @Override public PublicKey getPublicKey() { return publicKey; } @Override public void setPublicKey(PublicKey publicKey) { this.publicKey = publicKey; } @Override public PrivateKey getPrivateKey() { return privateKey; } @Override public void setPrivateKey(PrivateKey privateKey) { this.privateKey = privateKey; } public PublicKey getPublicKey(byte[] publicKey) throws CryptoException { KeyFactory keyFactory = null; PublicKey pubKey = null; X509EncodedKeySpec ukeySpec = new X509EncodedKeySpec(publicKey); try { keyFactory = KeyFactory.getInstance(CryptoConstant.ALG_RSA); pubKey = keyFactory.generatePublic(ukeySpec); } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_CONVERT_RSA_KEY_FAIL, e.getMessage()); } return pubKey; } public PrivateKey getPrivateKey(byte[] decPrivKey) throws CryptoException { PrivateKey privateKey = null; try{ PKCS8EncodedKeySpec rkeySpec = new PKCS8EncodedKeySpec(decPrivKey); KeyFactory rkeyFactory = KeyFactory.getInstance(CryptoConstant.ALG_RSA); privateKey = rkeyFactory.generatePrivate(rkeySpec); } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_CONVERT_RSA_KEY_FAIL, e.getMessage()); } return privateKey; } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/signature/EccSignatureProvider.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.signature; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import org.omnione.did.crypto.constant.CryptoConstant; import org.omnione.did.crypto.ec.CompactSign; import org.omnione.did.crypto.enums.DidKeyType; import org.omnione.did.crypto.enums.EccCurveType; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; import org.omnione.did.crypto.util.CryptoUtils; public class EccSignatureProvider implements SignatureProvider { public static CompactSign compactSign = new CompactSign(); /** * Generates an ECDSA signature from the given hashed data. * * @param privateKey The private key used for signing * @param hashedSource The original hashed data to be signed * @param eccCurveType The type of ECC curve to use * @return The ECDSA signature in ASN.1 DER format * @throws CryptoException */ public byte[] generateSignatureFromHashedData(PrivateKey privateKey, byte[] hashedSource) throws CryptoException { byte[] signData = null; try { Signature signature = null; try { signature = Signature.getInstance(CryptoConstant.SIG_ALG_NONE_ECDSA, CryptoConstant.PROVIDER_BC); } catch (NoSuchAlgorithmException | NoSuchProviderException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_SIGN_VALUE, e.getMessage()); } signature.initSign(privateKey); signature.update(hashedSource); signData = signature.sign(); } catch (SignatureException | InvalidKeyException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_SIGN_VALUE, e.getMessage()); } return signData; } /** * Converts an ECDSA signature in ASN.1 DER format to a compact signature. * * @param publicKey The public key corresponding to the private key used for signing * @param source The original hashed data to be signed * @param signData The ECDSA signature in ASN.1 DER format * @param eccCurveType The type of ECC curve to use * @return The compact signature * @throws CryptoException */ public byte[] convertToCompactSignature(PublicKey publicKey, byte[] source, byte[] signData, EccCurveType eccCurveType) throws CryptoException { byte[] compressedPubKey = null; compressedPubKey = CryptoUtils.compressPublicKey(publicKey.getEncoded(), eccCurveType); return compactSign.getSignBytes(compressedPubKey, source, signData, eccCurveType.getCurveName()); } /** * Verifies a compact signature using a compressed public key. * * @param compressedpublicKeyBytes The compressed public key bytes * @param source The original hashed data that was signed * @param signatureBytes The compact signature bytes * @param eccCurveType The type of ECC curve to use * @throws CryptoException */ public void verifyCompactSignWithCompressedKey(byte[] compressedpublicKeyBytes, byte[] source, byte[] signatureBytes, EccCurveType eccCurveType) throws CryptoException { compactSign.verifySign(compressedpublicKeyBytes, source, signatureBytes, eccCurveType.getCurveName()); } /** * Retrieves the ECC curve type corresponding to the given DID key type. * * @param didKeyType The DID key type * @return The corresponding ECC curve type * @throws CryptoException */ public static EccCurveType getECTypeFromDidKeyType(DidKeyType didKeyType) throws CryptoException { switch (didKeyType) { case SECP256K1_VERIFICATION_KEY_2018: return EccCurveType.Secp256k1; case SECP256R1_VERIFICATION_KEY_2018: return EccCurveType.Secp256r1; default: throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_INVALID_DID_KEY_TYPE); } } /** * Retrieves the signature algorithm corresponding to the given DID key type. * * @param didKeyType The DID key type * @return The corresponding signature algorithm * @throws CryptoException */ public static String getSignatureAlgorithm(DidKeyType didKeyType) throws CryptoException { switch (didKeyType) { case RSA_VERIFICATION_KEY_2018: return "SHA256withRSA"; case SECP256K1_VERIFICATION_KEY_2018: case SECP256R1_VERIFICATION_KEY_2018: return "SHA256withECDSA"; default: throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_INVALID_DID_KEY_TYPE); } } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/signature/SignatureProvider.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.signature; import java.security.PrivateKey; import java.security.PublicKey; public interface SignatureProvider { } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/util/CryptoUtils.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.util; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.jce.spec.ECPublicKeySpec; import org.bouncycastle.math.ec.ECPoint; import org.omnione.did.crypto.constant.CryptoConstant; import org.omnione.did.crypto.engines.AesEngine; import org.omnione.did.crypto.engines.CipherInfo; import org.omnione.did.crypto.enums.DidKeyType; import org.omnione.did.crypto.enums.EccCurveType; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; import org.omnione.did.crypto.generator.EcKeyPairGenerator; import org.omnione.did.crypto.generator.GenerateSecureRandom; import org.omnione.did.crypto.generator.RsaKeyPairGenerator; import org.omnione.did.crypto.keypair.KeyPairInterface; public class CryptoUtils { static { Security.addProvider(new BouncyCastleProvider()); } private static final RsaKeyPairGenerator rsaKeyPairGenerator = new RsaKeyPairGenerator(); private static final EcKeyPairGenerator ecKeyPairGenerator = new EcKeyPairGenerator(); private static final GenerateSecureRandom generateSecureRandom = new GenerateSecureRandom(); private static final AesEngine aesEngine = new AesEngine(); /** * Generate ECC KeyPair * * @param DidKeyType The type of DID key (e.g., RSA or specific ECC curve) * @return KeyPairInterface The generated key pair * @throws CryptoException */ public static KeyPairInterface generateKeyPair(DidKeyType didKeyType) throws CryptoException{ if(DidKeyType.RSA_VERIFICATION_KEY_2018 == didKeyType) { return rsaKeyPairGenerator.generateKeyPair(); } else if (DidKeyType.SECP256K1_VERIFICATION_KEY_2018 == didKeyType){ return ecKeyPairGenerator.generateKeyPair(EccCurveType.Secp256k1); } else if (DidKeyType.SECP256R1_VERIFICATION_KEY_2018 == didKeyType) { return ecKeyPairGenerator.generateKeyPair(EccCurveType.Secp256r1); } else { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_INVALID_DID_KEY_TYPE); } } /** * Compress ECC PublicKey * * @param unCompressedPublicKeyBytes The uncompressed ECC public key bytes * @param eccCurveType The ECC curve type * @return The compressed ECC public key bytes * @throws CryptoException */ public static byte[] compressPublicKey(byte[] unCompressedPublicKeyBytes, EccCurveType eccCurveType) throws CryptoException{ KeyFactory keyFactory; ECPublicKey publicKey = null; try { keyFactory = KeyFactory.getInstance(CryptoConstant.PROVIDER_EC, CryptoConstant.PROVIDER_BC); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(unCompressedPublicKeyBytes); publicKey = (ECPublicKey) keyFactory.generatePublic(publicKeySpec); } catch (NoSuchAlgorithmException | NoSuchProviderException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_COMPRESS_PUBLIC_KEY_FAIL, e.getMessage()); } catch (InvalidKeySpecException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_COMPRESS_PUBLIC_KEY_FAIL, e.getMessage()); } ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(eccCurveType.getCurveName()); ECPoint point = ecSpec.getCurve().createPoint(publicKey.getW().getAffineX(), publicKey.getW().getAffineY()); byte[] compressedPublicKey = point.getEncoded(true); return compressedPublicKey; } /** * Uncompress ECC PublicKey * * @param compressedPublicKey The compressed ECC public key bytes * @param eccCurveType The ECC curve type * @return The uncompressed ECC public key bytes * @exception CryptoException * @throws CryptoException */ public static byte[] unCompressPublicKey(byte[] compressedPublicKey, EccCurveType eccCurveType) throws CryptoException{ byte[] uncompressPublicKey = null; ECNamedCurveParameterSpec ecParams = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec(eccCurveType.getCurveName()); ECPoint uncompressedPoint = ecParams.getCurve().decodePoint(compressedPublicKey); ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(uncompressedPoint, ecParams); KeyFactory keyFactory; try { keyFactory = KeyFactory.getInstance(CryptoConstant.PROVIDER_EC, CryptoConstant.PROVIDER_BC); uncompressPublicKey = keyFactory.generatePublic(pubKeySpec).getEncoded(); } catch (NoSuchAlgorithmException | NoSuchProviderException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_COMPRESS_PUBLIC_KEY_FAIL, e.getMessage()); } catch (InvalidKeySpecException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_COMPRESS_PUBLIC_KEY_FAIL, e.getMessage()); } return uncompressPublicKey; } /** * Generate Nonce * * @return The generated nonce * @throws CryptoException */ public static byte[] generateNonce(int length) throws CryptoException { return generateSecureRandom.generateSecureRandom(length); } /** * Generate Salt * * @return The generated salt * @throws CryptoException */ public static byte[] generateSalt() throws CryptoException { return generateSecureRandom.generateSalt(); } /** * Generate SharedSecret * * @param compressedPublicKeyBytes The compressed ECC public key bytes * @param privateKeyBytes The private key bytes * @param eccCurveType The ECC curve type * @return The generated shared secret * @throws CryptoException */ public static byte[] generateSharedSecret(byte[] compressedPublicKeyBytes, byte[] privateKeyBytes, EccCurveType eccCurveType) throws CryptoException{ byte[] unCompressedPublicKeyBytes = unCompressPublicKey(compressedPublicKeyBytes, eccCurveType) ; KeyFactory keyFactory; ECPoint P = null; try { keyFactory = KeyFactory.getInstance(CryptoConstant.PROVIDER_EC, CryptoConstant.PROVIDER_BC); ECPrivateKey ecPrivateKey = (ECPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes)); ECPublicKey ecPublicKey = (ECPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(unCompressedPublicKeyBytes)); ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters) ECUtil.generatePrivateKeyParameter(ecPrivateKey); ECPublicKeyParameters pubKeyParams = (ECPublicKeyParameters) ECUtil.generatePublicKeyParameter(ecPublicKey); P = pubKeyParams.getQ().multiply(privKeyParams.getD()).normalize(); } catch (NoSuchAlgorithmException | NoSuchProviderException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_GEN_SECRET_FAIL, e.getMessage()); } catch (InvalidKeySpecException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_GEN_SECRET_FAIL, e.getMessage()); } catch (InvalidKeyException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_GEN_SECRET_FAIL, e.getMessage()); } if (P.isInfinity()) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_GEN_SECRET_FAIL, "Infinity is not a valid agreement value for ECDH"); } BigInteger bitInt = P.getAffineXCoord().toBigInteger(); byte[] sharedSecret = bitInt.toByteArray(); if (sharedSecret[0] == 0) { sharedSecret = Arrays.copyOfRange(sharedSecret, 1, sharedSecret.length); } return sharedSecret; } /** * Key Derivation Function By pbkdf2 * * @param password The password to derive the key from * @param salt The salt to use in the key derivation * @param iterator The number of iterations for the key derivation function * @param keySize The desired size of the derived key * @return derived byte[] key * @throws CryptoException */ public static byte[] pbkdf2(char[] password, byte[] salt, int iterator, int keySize) throws CryptoException { SecretKeySpec skeySpec = null; try { // Derive the key SecretKeyFactory factory = SecretKeyFactory.getInstance(CryptoConstant.PBKDF2_ALG_HMAC_SHA1); PBEKeySpec spec = new PBEKeySpec(password, salt, iterator, keySize); // Secret Key SecretKey secretKey = factory.generateSecret(spec); skeySpec = new SecretKeySpec(secretKey.getEncoded(), CryptoConstant.ALG_AES); return skeySpec.getEncoded(); } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_CRYPTOUTIL_GEN_SECRET_FAIL, e.getMessage()); } } /** * AES Encrypt * * @param source The plaintext data to encrypt * @param cipherInfo The cipher information (e.g., algorithm, mode, padding) * @param key The encryption key * @param iv The initialization vector * @return The encrypted data * @throws CryptoException */ public static byte[] encrypt(byte[] source, CipherInfo cipherInfo, byte[] key, byte[] iv) throws CryptoException { return aesEngine.aesEncryptDecrypt(source, cipherInfo, key, iv, Cipher.ENCRYPT_MODE); } /** * AES Decrypt * * @param cipherText The encrypted data to decrypt * @param cipherInfo The cipher information (e.g., algorithm, mode, padding) * @param key The decryption key * @param iv The initialization vector * @return The decrypted (plaintext) data * @throws CryptoException */ public static byte[] decrypt(byte[] cipherText, CipherInfo cipherInfo, byte[] key, byte[] iv) throws CryptoException { return aesEngine.aesEncryptDecrypt(cipherText, cipherInfo, key, iv, Cipher.DECRYPT_MODE); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/util/DigestUtils.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.util; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.omnione.did.crypto.constant.CryptoConstant; import org.omnione.did.crypto.enums.DigestType; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; public class DigestUtils { /** * Generate Digest Data * * @param source The source data to generate the digest from * @param digestType The type of digest algorithm to use (e.g., SHA-256, SHA-384, SHA-512) * @return The generated digest data * @throws CryptoException */ public static byte[] getDigest(byte[] source, DigestType digestType) throws CryptoException { if (source == null || digestType == null) { throw new CryptoException(CryptoErrorCode.ERR_CODE_DIGESTUTIL_HASH_TYPE_OR_SOURCE_IS_NULL); } switch(digestType) { case SHA256: return getShaDigest(source, CryptoConstant.HASH_ALG_SHA256); case SHA384: return getShaDigest(source, CryptoConstant.HASH_ALG_SHA384); case SHA512: return getShaDigest(source, CryptoConstant.HASH_ALG_SHA512); default: throw new CryptoException(CryptoErrorCode.ERR_CODE_DIGESTUTIL_INVALID_HASH_TYPE); } } /** * Generate SHA Digest * * @param source The source data to generate the SHA digest from * @param algorithm The SHA algorithm to use (e.g., SHA-256, SHA-384, SHA-512) * @return The generated SHA digest data * @throws CryptoException */ private static byte[] getShaDigest(byte[] source, String algorithm) throws CryptoException { try { MessageDigest digest = MessageDigest.getInstance(algorithm); return digest.digest(source); } catch (NoSuchAlgorithmException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_DIGESTUTIL_GEN_HASH_FAIL, e.getMessage()); } } /** * Merge ClientNonce and ServerNonce * * @param clientNonce The client nonce bytes to merge * @param serverNonce The server nonce bytes to merge * @return The merged nonce bytes * @exception CryptoException */ public static byte[] mergeNonce(byte[] clientNonce, byte[] serverNonce) throws CryptoException { if (clientNonce == null || serverNonce == null) { throw new CryptoException(CryptoErrorCode.ERR_CODE_DIGESTUTIL_HASH_TYPE_OR_SOURCE_IS_NULL); } MessageDigest digest; try { digest = MessageDigest.getInstance("SHA-256"); digest.update(clientNonce, 0, clientNonce.length); digest.update(serverNonce, 0, serverNonce.length); return digest.digest(); } catch (NoSuchAlgorithmException e) { throw new CryptoException(CryptoErrorCode.ERR_CODE_DIGESTUTIL_GEN_HASH_FAIL, e.getMessage()); } } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/util/MultiBaseUtils.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.util; import org.omnione.did.crypto.encoding.Base58; import org.omnione.did.crypto.enums.MultiBaseType; import org.omnione.did.crypto.exception.CryptoException; import org.omnione.did.crypto.exception.CryptoErrorCode; import java.util.*; public class MultiBaseUtils { /** * Encoding * * @param source The source bytes to encode * @param baseType The type of base encoding to use (e.g., base16, base58btc, base64, base64url) * @return The encoded string * @throws CryptoException */ public static String encode(byte[] source, MultiBaseType baseType) throws CryptoException { String character = baseType.getCharacter(); switch (baseType){ case base16: String enc16Data = HexFormat.of().formatHex(source); StringBuilder sb16 = new StringBuilder(enc16Data); sb16.insert(0, character); return new String(sb16); case base16upper: String enc16UpperData = HexFormat.of().withUpperCase().formatHex(source); StringBuilder sb16Upper = new StringBuilder(enc16UpperData); sb16Upper.insert(0, character); return new String(sb16Upper); case base58btc: String enc58Data = Base58.encode(source); StringBuilder sb58 = new StringBuilder(enc58Data); sb58.insert(0, character); return new String(sb58); case base64: String enc64Data = Base64.getEncoder().withoutPadding().encodeToString(source); StringBuilder sb64 = new StringBuilder(enc64Data); sb64.insert(0, character); return new String(sb64); case base64url: String enc64urlData = Base64.getUrlEncoder().withoutPadding().encodeToString(source); StringBuilder sb64url = new StringBuilder(enc64urlData); sb64url.insert(0, character); return new String(sb64url); default: throw new CryptoException(CryptoErrorCode.ERR_CODE_MULTIBASEUTIL_INVALID_ENCODING_TYPE); } } /** * Decoding * * @param multibase The encoded string to decode * @return The decoded bytes * @throws CryptoException */ public static byte[] decode(String multibase) throws CryptoException { if (multibase == null || multibase.length() < 2) { return null; } String firstString = multibase.substring(0, 1); String remainString = multibase.substring(1); MultiBaseType baseType = getMultibaseEnum(firstString); if (baseType == null) { return null; } switch (baseType) { case base16: return HexFormat.of().parseHex(remainString); case base16upper: return HexFormat.of().parseHex(remainString); case base58btc: return Base58.decode(remainString); case base64: return Base64.getDecoder().decode(padBase64String(remainString)); case base64url: return Base64.getUrlDecoder().decode(padBase64String(remainString)); default: throw new CryptoException(CryptoErrorCode.ERR_CODE_MULTIBASEUTIL_INVALID_DECODING_TYPE); } } /** * Encoding Type Check * * @param firstString The first character of the encoded string to determine the encoding type * @return The corresponding MultiBaseType enum */ private static MultiBaseType getMultibaseEnum(String firstString) { for (MultiBaseType baseType : MultiBaseType.values()) { if (baseType.getCharacter().equals(firstString)) { return baseType; } } return null; } /** * Pad Base64 String * * @param base64 The base64 string to pad * @return The padded base64 string */ private static String padBase64String(String base64) { int paddingCount = (4 - (base64.length() % 4)) % 4; StringBuilder sb = new StringBuilder(base64); for (int i = 0; i < paddingCount; i++) { sb.append('='); } return sb.toString(); } } ================================================ FILE: source/did-crypto-sdk-server/src/main/java/org/omnione/did/crypto/util/SignatureUtils.java ================================================ /* * Copyright 2024 OmniOne. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.omnione.did.crypto.util; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.omnione.did.crypto.enums.EccCurveType; import org.omnione.did.crypto.exception.CryptoErrorCode; import org.omnione.did.crypto.exception.CryptoException; import org.omnione.did.crypto.keypair.EcKeyPair; import org.omnione.did.crypto.signature.EccSignatureProvider; public class SignatureUtils { public static EccSignatureProvider eccSignatureProvider = new EccSignatureProvider(); static { Security.addProvider(new BouncyCastleProvider()); } /** * Generates a compact ECDSA signature using the given EC key pair and hashed data. * * @param keyPair The EC key pair containing both the private and public keys * @param hashedSource The original hashed data to be signed * @param eccCurveType The ECC curve type used for generating the signature * @return a byte array containing the compact ECDSA signature * @throws CryptoException */ public static byte[] generateCompactSignature(EcKeyPair keyPair, byte[] hashedSource, EccCurveType eccCurveType) throws CryptoException { if (keyPair == null || keyPair.getPrivateKey() == null || keyPair.getPublicKey() == null) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "KeyPair is null"); } if (hashedSource == null || hashedSource.length == 0) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "Hashed Source is null"); } if (eccCurveType == null) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "EccCurve Type is null"); } byte[] signaure = generateEccSignatureFromHashedData(keyPair.getPrivateKey(), hashedSource); byte[] compactSignarue = convertToCompactSignature(keyPair.getPublicKey(), hashedSource, signaure, eccCurveType); return compactSignarue; } /** * Generates an ECDSA signature in ASN.1 DER format from hashed data using the given private key and ECC curve type. * * @param privateKey The private key used for generating the signature * @param hashedSource The original hashed data to be signed * @return a byte array containing the ECDSA signature in ASN.1 DER format * @throws CryptoException */ public static byte[] generateEccSignatureFromHashedData(PrivateKey privateKey, byte[] hashedSource) throws CryptoException { if (privateKey == null) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "Private Key is null"); } if (hashedSource == null || hashedSource.length == 0) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "Hashed Source is null"); } return eccSignatureProvider.generateSignatureFromHashedData(privateKey, hashedSource); } /** * Converts an ECDSA signature in ASN.1 DER format to a compact format using the given public key, hashed data, and ECC curve type. * * @param publicKey The public key corresponding to the private key used for signing * @param hashedSource The original hashed data to be signed * @param signatureBytes The original ECDSA signature bytes in ASN.1 DER format * @param eccCurveType The ECC curve type used for generating the signature * @return a byte array containing the compact ECDSA signature * @throws CryptoException */ public static byte[] convertToCompactSignature(PublicKey publicKey, byte[] hashedsource, byte[] signatureBytes, EccCurveType eccCurveType) throws CryptoException { if (publicKey == null ) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "Public Key is null"); } if (hashedsource == null || hashedsource.length == 0 ) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "Hashed Source is null"); } if (signatureBytes == null || signatureBytes.length == 0 ) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "SignatureBytes is null"); } if (eccCurveType == null) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "EccCurve Type is null"); } return eccSignatureProvider.convertToCompactSignature(publicKey, hashedsource, signatureBytes, eccCurveType); } /** * Verifies a compact ECDSA signature using the given compressed public key, hashed data, and ECC curve type. * * @param compressedPublicKeyBytes The compressed public key bytes used for verifying the signature * @param hashedSource The original hashed data to be signed * @param signatureBytes The compact ECDSA signature bytes * @param eccCurveType The ECC curve type used for generating the signature * @throws CryptoException */ public static void verifyCompactSignWithCompressedKey(byte[] compressedpublicKeyBytes, byte[] hashedsource, byte[] signatureBytes, EccCurveType eccCurveType) throws CryptoException { if (compressedpublicKeyBytes == null || compressedpublicKeyBytes.length != 33) { throw new CryptoException( CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "Compressed PublicKeyBytes is null"); } if (hashedsource == null || hashedsource.length == 0) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "Hashed Source is null"); } if (signatureBytes == null || signatureBytes.length == 0) { throw new CryptoException(CryptoErrorCode.ERR_CODE_SIGNATUREUTIL_INVALID_PARAM, "SignatureBytes is null"); } eccSignatureProvider.verifyCompactSignWithCompressedKey(compressedpublicKeyBytes, hashedsource, signatureBytes, eccCurveType); } }