Showing preview only (517K chars total). The displayed content is truncated. Use the JSON API for full output.
Repository: terl/lazysodium-java
Branch: master
Commit: e18332d87400
Files: 81
Total size: 488.4 KB
Directory structure:
gitextract_988v69l7/
├── .github/
│ └── workflows/
│ └── primary.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── azure-pipelines.yml
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── sample-app/
│ ├── build.gradle
│ ├── libs/
│ │ └── jansi.jar
│ └── src/
│ └── main/
│ └── kotlin/
│ └── Main.kt
├── settings.gradle
└── src/
├── main/
│ └── java/
│ └── com/
│ └── goterl/
│ └── lazysodium/
│ ├── LazySodium.java
│ ├── LazySodiumJava.java
│ ├── Sodium.java
│ ├── SodiumJava.java
│ ├── exceptions/
│ │ └── SodiumException.java
│ ├── interfaces/
│ │ ├── AEAD.java
│ │ ├── Auth.java
│ │ ├── Base.java
│ │ ├── Box.java
│ │ ├── DiffieHellman.java
│ │ ├── GenericHash.java
│ │ ├── Hash.java
│ │ ├── Helpers.java
│ │ ├── KeyDerivation.java
│ │ ├── KeyExchange.java
│ │ ├── MessageEncoder.java
│ │ ├── Padding.java
│ │ ├── PwHash.java
│ │ ├── Random.java
│ │ ├── Ristretto255.java
│ │ ├── Scrypt.java
│ │ ├── SecretBox.java
│ │ ├── SecretStream.java
│ │ ├── SecureMemory.java
│ │ ├── ShortHash.java
│ │ ├── Sign.java
│ │ ├── Stream.java
│ │ └── StreamJava.java
│ └── utils/
│ ├── Base64Facade.java
│ ├── Base64Java.java
│ ├── Base64MessageEncoder.java
│ ├── BaseChecker.java
│ ├── Constants.java
│ ├── Detached.java
│ ├── DetachedDecrypt.java
│ ├── DetachedEncrypt.java
│ ├── HexMessageEncoder.java
│ ├── Key.java
│ ├── KeyPair.java
│ ├── LibraryLoader.java
│ ├── LibraryLoadingException.java
│ └── SessionPair.java
└── test/
└── java/
└── com/
└── goterl/
└── lazysodium/
├── AEADTest.java
├── AuthTest.java
├── BaseTest.java
├── BoxTest.java
├── DiffieHellmanTest.java
├── GenericHashTest.java
├── HashTest.java
├── HelperTest.java
├── KeyDerivationTest.java
├── KeyExchangeTest.java
├── PaddingTest.java
├── PwHashTest.java
├── Ristretto255Test.java
├── SecretBoxTest.java
├── SecretStreamTest.java
├── SecureMemoryTest.java
├── ShortHashTest.java
├── SignTest.java
├── SodiumJavaTest.java
├── StreamTest.java
└── utils/
├── Base64MessageEncoderTest.java
├── HexMessageEncoderTest.java
└── SodiumConversionsTest.java
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/primary.yml
================================================
name: Checks
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
test:
name: ${{ matrix.os }} ${{ matrix.arch }} check
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
arch: [x64]
steps:
- uses: actions/checkout@v3
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '21'
architecture: ${{ matrix.arch }}
- name: Test with Gradle
run: ./gradlew test
test-on-mac-arm:
name: ${{ matrix.os }} ${{ matrix.arch }} check
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest]
arch: [arm64]
steps:
- uses: actions/checkout@v3
- name: Set up Java on ARM64
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '21'
- name: Test with Gradle
run: ./gradlew test
publish:
name: Publish to snapshot repo if master branch
runs-on: ubuntu-latest
needs: [test, test-on-mac-arm]
if: github.ref == 'refs/heads/master' && always()
steps:
- uses: technote-space/workflow-conclusion-action@v3
- uses: actions/checkout@v3
if: env.WORKFLOW_CONCLUSION == 'success'
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 21
if: env.WORKFLOW_CONCLUSION == 'success'
- name: Import GPG key
id: import_gpg
uses: crazy-max/ghaction-import-gpg@v3
with:
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
if: env.WORKFLOW_CONCLUSION == 'success'
- name: Publish
run: ./gradlew publishSnapshotPublicationToSnapshotRepository -Psigning.gnupg.keyName="${{ secrets.GPG_SIGNING_SUBKEY_ID }}" -Psigning.password="${{ secrets.GPG_PASSPHRASE }}" -PossrhUsername="${{ secrets.SONATYPE_USER }}" -PossrhPassword="${{ secrets.SONATYPE_PASSWORD }}"
if: env.WORKFLOW_CONCLUSION == 'success'
================================================
FILE: .gitignore
================================================
# Compiled source #
###################
*.com
*.class
*.exe
*.o
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# IntelliJ #
################
.idea/*
!.idea/copyright/Terl_Tech_Ltd___MPLv2.xml
*.ipr
*.iws
*.iml
atlassian-ide-plugin.xml
# Gradle Files #
################
.gradle
.m2
local.properties
# Build output directies #
################
target/
build/
out/
# Eclipse #
################
.classpath
.project
.settings
.metadata
# Netbeans #
################
.nbattrs
================================================
FILE: CHANGELOG.md
================================================
Please see the releases page on github https://github.com/terl/lazysodium-java/releases
================================================
FILE: LICENSE.md
================================================
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
================================================
FILE: README.md
================================================
<p align="center"><img width="260" src="https://filedn.com/lssh2fV92SE8dRT5CWJvvSy/lazysodium_large_transparent.png" /></p>
# Lazysodium for Java
Lazysodium is a **complete** Java (JNA) wrapper over the [Libsodium](https://github.com/jedisct1/libsodium) library that provides developers with a **smooth and effortless** cryptography experience.
[](https://github.com/terl/lazysodium-java/actions/workflows/primary.yml)

## Features
**This library is fully compatible with Kotlin.**
You can find an up-to-date feature list [here](https://github.com/terl/lazysodium-java/wiki/features).
## Quick start
Please view the [official documentation](https://github.com/terl/lazysodium-java/wiki/installation) for a more comprehensive guide.
The following example is for users of the build tool Gradle:
```groovy
// Top level build file
repositories {
// Add this to the end of any existing repositories
mavenCentral()
}
// Project level dependencies section
dependencies {
implementation "com.goterl:lazysodium-java:VERSION_NUMBER"
implementation "net.java.dev.jna:jna:JNA_NUMBER"
}
```
Substitute `VERSION_NUMBER` for the version in this box:

Substitute `JNA_NUMBER` for the [latest version of JNA](https://github.com/java-native-access/jna/releases).
## Documentation
Please view our [official documentation](https://github.com/terl/lazysodium-java/wiki) to get started.
## Examples
There are some example projects available [here](https://github.com/terl/lazysodium-java/tree/master/sample-app).
## Lazysodium for Android
We also have an Android implementation available at [Lazysodium for Android](https://github.com/terl/lazysodium-android). It has the same API as this library, so you can share code easily!
---
<a href="https://terl.co"><img width="100" style="float: left: display: inline;" src="https://filedn.com/lssh2fV92SE8dRT5CWJvvSy/terl.png" /></a>
Created by [Terl](https://terl.co).
================================================
FILE: azure-pipelines.yml
================================================
# DEPRECATED.
# Azure Pipelines has been deprecated in favour of
# GitHub Actions. See the .github/workflows folder
# Build your Java project and run tests with Gradle using a Gradle wrapper script.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/java
trigger:
- master
strategy:
matrix:
linux:
imageName: 'ubuntu-16.04'
mac:
imageName: 'macos-10.14'
windows:
imageName: 'vs2017-win2016'
pool:
vmImage: $(imageName)
steps:
- task: Gradle@2
inputs:
workingDirectory: ''
options: "--stacktrace --info"
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '1.8'
jdkArchitectureOption: 'x64'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'test'
================================================
FILE: build.gradle
================================================
/*
* Copyright (c) Terl Tech Ltd • 14/06/19 17:54 • goterl.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
plugins {
id 'application'
id 'java-library'
id 'maven-publish'
id 'org.jreleaser' version '1.18.0'
id 'signing'
id 'biz.aQute.bnd.builder'
}
ext {
artifactId = "lazysodium-java"
groupId = "com.goterl"
version = '5.2.0'
description = "Lazysodium (Java) makes it effortless for Java " +
"developers to get started with Libsodium's cryptography."
}
repositories {
mavenCentral()
}
group project.ext.groupId
version = project.ext.version
mainClassName = "com.goterl.lazysodium.LazySodium"
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
sourceSets {
main {
resources {
srcDirs "src/main/resources"
}
}
}
processResources {
setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE)
}
test {
useJUnitPlatform()
}
// Dependencies
dependencies {
implementation 'net.java.dev.jna:jna:5.17.0'
implementation 'com.goterl:resource-loader:2.1.0'
implementation "org.slf4j:slf4j-api:2.0.17"
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.12.2'
testRuntimeOnly 'org.junit.platform:junit-platform-engine:1.12.2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.12.2'
}
// Tasks
signing {
// This will use the GPG Agent
// to sign the jar
useGpgCmd()
sign publishing.publications
}
task sourcesJar(type: Jar, dependsOn: classes) {
setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE)
archiveClassifier = 'sources'
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: javadoc) {
setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE)
archiveClassifier = 'javadoc'
from javadoc.destinationDir
}
tasks.named('jar') {
setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE)
manifest {
attributes('Automatic-Module-Name': 'com.goterl.lazysodium')
}
}
task signPom(type: Sign) {
sign project.file("$buildDir/publications/release/pom-default.xml")
// The signing plugin does not seem to notice
// it when the publications folder with the
// signature has been deleted. So we always
// create a new signature
outputs.upToDateWhen { false }
}
artifacts {
archives sourcesJar, javadocJar
}
void loadProps() {
File secretPropsFile = project.rootProject.file('local.properties')
if (secretPropsFile.exists()) {
Properties p = new Properties()
new FileInputStream(secretPropsFile).withCloseable { is ->
p.load(is)
}
p.each { name, value ->
ext[name] = value
}
}
}
loadProps()
// Return an empty string if a property
// cannot be found
String getProp(String propName) {
if (ext.hasProperty(propName) != null) {
return ext[propName]
} else {
return ""
}
}
String getSonatypeUserName() {
return findProperty("ossrhUsername")
}
String getSonatypePassword() {
return findProperty("ossrhPassword")
}
Closure createPomClosure = {
def root = asNode()
root.appendNode('description', project.ext.description)
root.appendNode('name', project.ext.artifactId)
root.appendNode('url', 'https://github.com/terl/lazysodium-java')
def scm = root.appendNode('scm')
scm.appendNode("connection", "scm:git:git://github.com/terl/lazysodium-java.git")
scm.appendNode("developerConnection", "scm:git:ssh://github.com/terl/lazysodium-java")
scm.appendNode("url", "http://github.com/terl/lazysodium-java")
def license = root.appendNode('licenses').appendNode('license')
license.appendNode('name', 'Mozilla Public License, Version 2.0')
license.appendNode('url', 'http://www.mozilla.org/MPL/2.0/index.txt')
license.appendNode('distribution', 'repo')
def developer = root.appendNode('developers').appendNode('developer')
developer.appendNode('name', 'Terl Tech Ltd')
developer.appendNode('email', 'hello@terl.co')
}
jreleaser {
signing {
active = 'ALWAYS'
mode = 'FILE'
armored = true
verify = true
passphrase = findProperty("signing.password")
publicKey = findProperty("key.public.path")
secretKey = findProperty("key.private.path")
}
release {
github {
token = findProperty("github.token")
repoOwner = "terl"
host = 'github.com'
username = 'gurpreet-'
branch = 'master'
}
}
deploy {
maven {
mavenCentral {
'release-deploy' {
active = 'RELEASE'
url = 'https://central.sonatype.com/api/v1/publisher'
applyMavenCentralRules = true
stagingRepository('build/staging-deploy')
username = getSonatypeUserName()
password = getSonatypePassword()
namespace = 'com.goterl'
}
}
nexus2 {
'snapshot-deploy' {
active = 'SNAPSHOT'
url = 'https://central.sonatype.com/repository/maven-snapshots'
snapshotUrl = 'https://central.sonatype.com/repository/maven-snapshots'
applyMavenCentralRules = true
snapshotSupported = true
closeRepository = true
releaseRepository = true
stagingRepository('build/staging-deploy')
username = getSonatypeUserName()
password = getSonatypePassword()
}
}
}
}
}
publishing {
publications {
maven(MavenPublication) {
from components.java
groupId project.ext.groupId
artifactId project.ext.artifactId
version project.ext.version
artifact sourcesJar
artifact javadocJar
pom.withXml createPomClosure
}
}
repositories {
maven {
url = layout.buildDirectory.dir('staging-deploy')
}
}
}
// Force character encoding in case the workspace was not set up correctly
tasks.withType(Javadoc) {
options.encoding = 'UTF-8'
}
tasks.withType(Test) {
// a collection to track failedTests
ext.failedTests = []
afterTest { descriptor, result ->
if (result.resultType == TestResult.ResultType.FAILURE) {
String failedTest = "${descriptor.className}::${descriptor.name}"
logger.debug("Adding " + failedTest + " to failedTests...")
failedTests << [failedTest]
}
}
afterSuite { suite, result ->
if (!suite.parent) { // will match the outermost suite
// logs each failed test
if (!failedTests.empty) {
logger.lifecycle("Failed tests:")
failedTests.each { failedTest ->
logger.lifecycle("${failedTest}")
}
}
}
}
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#
# Copyright (c) Terl Tech Ltd • 14/06/19 17:54 • goterl.com
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at http://mozilla.org/MPL/2.0/.
#
#Tue May 01 23:05:44 BST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
================================================
FILE: gradle.properties
================================================
#
# Copyright (c) Terl Tech Ltd • 14/06/19 17:54 • goterl.com
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at http://mozilla.org/MPL/2.0/.
#
================================================
FILE: gradlew
================================================
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# 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
;;
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"
which java >/dev/null 2>&1 || 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
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
================================================
FILE: gradlew.bat
================================================
@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=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@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=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
: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 %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="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!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: sample-app/build.gradle
================================================
plugins {
id 'org.jetbrains.kotlin.jvm' version '2.2.0-RC'
id 'java'
id 'application'
}
group 'com.goterl'
version '1.0.0'
mainClassName = "Main"
repositories {
mavenCentral()
maven {
name = 'Central Portal Snapshots'
url = 'https://central.sonatype.com/repository/maven-snapshots/'
// Only search this repository for the specific dependency
content {
includeModule("com.goterl", "lazysodium-java")
}
}
}
kotlin {
jvmToolchain(21)
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "net.java.dev.jna:jna:5.12.0"
implementation 'com.goterl:lazysodium-java:5.1.5-SNAPSHOT'
}
================================================
FILE: sample-app/src/main/kotlin/Main.kt
================================================
import com.goterl.lazysodium.LazySodium
import com.goterl.lazysodium.LazySodiumJava
import com.goterl.lazysodium.SodiumJava
import com.goterl.lazysodium.exceptions.SodiumException
import com.goterl.lazysodium.interfaces.*
import com.goterl.lazysodium.utils.Key
import com.goterl.lazysodium.utils.KeyPair
import com.goterl.lazysodium.utils.LibraryLoader
import com.sun.jna.NativeLong
import org.fusesource.jansi.Ansi
import org.fusesource.jansi.Ansi.ansi
import org.fusesource.jansi.AnsiConsole
class Main(private val parsed: Int) {
private val lazySodium = LazySodiumJava(SodiumJava(LibraryLoader.Mode.BUNDLED_ONLY))
fun run() {
try {
if (parsed == 1) {
symmetricKeyEncryptionStep1()
}
if (parsed == 2) {
publicPrivateKeyEncryptionStep1()
}
if (parsed == 3) {
genericHashStep1()
genericHashStep1b()
genericHashStep2()
}
if (parsed == 4) {
pwHashStep1()
}
if (parsed == 5) {
sign()
signWithNonRandomKeys()
}
} catch (e: SodiumException) {
e.printStackTrace()
}
}
@Throws(SodiumException::class)
private fun sign() {
printSection("Running sign detached")
val msg = "This message needs to be signed"
val kp: KeyPair = lazySodium.cryptoSignKeypair()
val pk: Key = kp.publicKey
val sk: Key = kp.secretKey
if (!lazySodium.cryptoSignKeypair(pk.asBytes, sk.asBytes)) {
throw SodiumException("Could not generate a signing keypair.")
}
printStep(
"1",
"Signing a message",
"We will be using the random secret key '" + sk.asHexString.toString() + "' and will be " +
"signing the message '" + msg + "'."
)
val messageBytes: ByteArray = lazySodium.bytes(msg)
val skBytes: ByteArray = sk.asBytes
val signatureBytes = ByteArray(Sign.BYTES)
lazySodium.cryptoSignDetached(signatureBytes, messageBytes, messageBytes.size.toLong(), skBytes)
val v: Boolean =
lazySodium.cryptoSignVerifyDetached(signatureBytes, messageBytes, messageBytes.size, pk.getAsBytes())
log()
logt("The signed message is " + LazySodium.toHex(signatureBytes) + ".")
logt("Verifying the signed message outputs true: $v.")
}
@Throws(SodiumException::class)
private fun signWithNonRandomKeys() {
val msg = "Sign this"
val pk: Key = Key.fromPlainString("edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav8888888888")
val sk: Key = Key.fromPlainString("edsk3gUfUPyBSfrS9CCgmCiQsTCHGkviBDusMxDJstFtojtc1zcpsh8888888888")
log()
printStep(
"2",
"Signing a message (non-random)",
("We will be using the non-random secret key '" + sk.asHexString.toString() + "' and will be " +
"signing the message '" + msg + "'.")
)
if (!lazySodium.cryptoSignKeypair(pk.asBytes, sk.asBytes)) {
throw SodiumException("Could not generate a signing keypair.")
}
val signed: String = lazySodium.cryptoSignDetached(msg, sk)
val verification: Boolean = lazySodium.cryptoSignVerifyDetached(signed, msg, pk)
log()
logt("The signed message is $signed.")
logt("Verifying the signed message outputs true: $verification.")
}
@Throws(SodiumException::class)
private fun symmetricKeyEncryptionStep1() {
printSection("Running symmetric key encryption")
val key: Key = lazySodium.cryptoSecretBoxKeygen()
val msg = "This message needs top security"
printStep(
"1",
"Encrypting a message with a symmetric key",
("We will be using the random key '" + key.getAsHexString().toString() + "' and will be " +
"encrypting the message '" + msg + "'.")
)
val nonce: ByteArray = lazySodium.nonce(SecretBox.NONCEBYTES)
val encrypted: String = lazySodium.cryptoSecretBoxEasy(msg, nonce, key)
log()
logt("The encrypted string is $encrypted.")
logt("You should also store the nonce " + lazySodium.toHexStr(nonce) + ".")
logt("The nonce can be stored in a public location.")
symmetricKeyEncryptionStep2(key, nonce, encrypted)
}
@Throws(SodiumException::class)
private fun symmetricKeyEncryptionStep2(key: Key, nonce: ByteArray, encrypted: String) {
log()
printStep(
"2",
"Decrypting a message with a symmetric key",
"We will now decrypt the message we encrypted in the previous step."
)
val decrypted: String = lazySodium.cryptoSecretBoxOpenEasy(encrypted, nonce, key)
log()
logt("The decrypted string is $decrypted.")
logt("It should equal the message we encrypted in step 1.")
}
@Throws(SodiumException::class)
private fun publicPrivateKeyEncryptionStep1() {
printSection("Running public private key encryption")
log()
printStep(
"1",
"Generating public private keypairs",
"In this step we'll generate public keys for Alice " +
"and Bob."
)
val aliceKp: KeyPair = lazySodium.cryptoBoxKeypair()
val bobKp: KeyPair = lazySodium.cryptoBoxKeypair()
log()
logt("Alice's public key: " + aliceKp.publicKey.asHexString)
logt("Bob's public key: " + bobKp.publicKey.asHexString)
log()
publicPrivateKeyEncryptionStep2(aliceKp, bobKp)
}
@Throws(SodiumException::class)
private fun publicPrivateKeyEncryptionStep2(aliceKp: KeyPair, bobKp: KeyPair) {
val message = "Cryptography is the best"
printStep(
"2",
"Encrypting a message with a public private keypair",
"Alice wants to send the message '$message' to Bob."
)
// Make sure that we provide the secret key of Alice encrypting
// the message using Bob's public key.
val aliceToBobKp = KeyPair(bobKp.publicKey, aliceKp.secretKey)
val nonce: ByteArray = lazySodium.nonce(Box.NONCEBYTES)
val encrypted: String = lazySodium.cryptoBoxEasy(message, nonce, aliceToBobKp)
log()
logt("Alice uses her private key to encrypt the message with Bob's public key.")
logt("Encryption result: $encrypted")
log()
publicPrivateKeyEncryptionStep3(encrypted, nonce, aliceKp, bobKp)
}
@Throws(SodiumException::class)
private fun publicPrivateKeyEncryptionStep3(encrypted: String, nonce: ByteArray, aliceKp: KeyPair, bobKp: KeyPair) {
// Make sure we have Bob's private key decrypting the message with
// Alice's public key.
val bobFromAliceKp = KeyPair(aliceKp.getPublicKey(), bobKp.getSecretKey())
val decrypted: String = lazySodium.cryptoBoxOpenEasy(encrypted, nonce, bobFromAliceKp)
logt("Bob uses his private key to decrypt the message.")
logt("Decryption result: '$decrypted'.")
log()
}
@Throws(SodiumException::class)
private fun genericHashStep1() {
printSection("Running generic hash")
// We can generate a random key or
// we can provide a key.
// String randomKey = lazySodium.cryptoGenericHashKeygen();
// Key must be larger than GenericHash.KEYBYTES_MIN
// but less than GenericHash.KEYBYTES_MAX
val key = "randomkeyoflength16bytes"
printStep(
"1",
"Deterministic key hash",
"The following hashes should be the same as we're using " +
"identical keys for them.",
"We will be using the key '$key'."
)
val hash: String = lazySodium.cryptoGenericHash("", Key.fromPlainString(key))
val hash2: String = lazySodium.cryptoGenericHash("", Key.fromPlainString(key))
log()
logt("Hash 1: $hash")
logt("Hash 2: $hash2")
logt("Hash 1 == Hash 2? " + hash.equals(hash2, ignoreCase = true))
log()
}
private fun printSection(sectionTitle: String) {
log(" ")
log(" >>> $sectionTitle.")
log(" ")
}
private fun printStep(step: String, title: String, vararg descriptions: String) {
log("+ Step $step: $title.")
for (desc: String in descriptions) {
log(" $desc")
}
}
@Throws(SodiumException::class)
private fun genericHashStep1b() {
val randomKey: ByteArray = lazySodium.randomBytesBuf(GenericHash.KEYBYTES)
printStep(
"1b",
"Deterministic key hash using Native",
"The following hashes should be the same as we're using " +
"identical keys for them.",
"We will be using the random key '" + lazySodium.toHexStr(randomKey) + "'."
)
val nativeGH: com.goterl.lazysodium.interfaces.GenericHash.Native =
lazySodium as com.goterl.lazysodium.interfaces.GenericHash.Native
val message: ByteArray = lazySodium.bytes("Top secret message.")
val hash: ByteArray = lazySodium.randomBytesBuf(GenericHash.BYTES)
val hash2: ByteArray = lazySodium.randomBytesBuf(GenericHash.BYTES)
val res: Boolean =
nativeGH.cryptoGenericHash(hash, hash.size, message, message.size.toLong(), randomKey, randomKey.size)
val res2: Boolean =
nativeGH.cryptoGenericHash(hash2, hash2.size, message, message.size.toLong(), randomKey, randomKey.size)
if (!res || !res2) {
throw SodiumException("Could not hash the message.")
}
val hash1Hex: String = lazySodium.toHexStr(hash)
val hash2Hex: String = lazySodium.toHexStr(hash2)
log()
logt("Hash 1: $hash1Hex")
logt("Hash 2: $hash2Hex")
logt("Hash 1 == Hash 2? " + hash1Hex.equals(hash2Hex, ignoreCase = true))
log()
}
@Throws(SodiumException::class)
private fun genericHashStep2() {
log("+ Step 2: Random key hash.")
log(
" The following hashes should be different as we're using" +
" random keys for them."
)
val hashRandom: String = lazySodium.cryptoGenericHash("", lazySodium.cryptoGenericHashKeygen())
val hashRandom2: String = lazySodium.cryptoGenericHash("", lazySodium.cryptoGenericHashKeygen())
log()
logt("Hash 1: $hashRandom")
logt("Hash 2: $hashRandom2")
logt("Hash 1 == Hash 2? " + hashRandom.equals(hashRandom2, ignoreCase = true))
log()
}
private fun pwHashStep1() {
printSection("Running password hashing")
val pw = "superAwesomePassword"
printStep(
"1",
"Hashing a password",
"Attempting to hash a password '$pw' using Argon 2."
)
try {
val hash: String = lazySodium.cryptoPwHashStr(pw, 2L, NativeLong(65536))
log()
logt("Password hashing successful: $hash")
log()
} catch (e: SodiumException) {
e.printStackTrace()
log()
logt("Password hashing failed with exception: " + e.message)
log()
}
pwHashStep2()
}
private fun pwHashStep2() {
val pw = "lol"
printStep(
"2",
"Multiple password verification (Native)",
("Verifying password '" + pw + "' using Argon2 many times. " +
"This may take a while...")
)
val pwBytes: ByteArray = lazySodium.bytes(pw)
// Remember the terminating byte (null byte) at the end of the hash!
// As this is using the Native interface you must always remember
// to add that null byte yourself. Use the Lazy interface if you
// don't want to handle any of that (as shown in the next step).
val hash: ByteArray = lazySodium.bytes(
"\$argon2id\$v=19\$m=65536,t=2,p=1\$ZrWMVZiMs4tvs0QwVc7T7A\$L" +
"Il6XlgIZsuozRpC3bCe5ew8LEWgDQvQE8qwsZ9ISps\u0000"
)
log()
var i = 0
while (i < 100) {
val result: Boolean = lazySodium.cryptoPwHashStrVerify(hash, pwBytes, pwBytes.size)
logt("Password hashing verification: $result")
i++
}
log()
pwHashStep3()
}
private fun pwHashStep3() {
val pw = "password"
printStep(
"2",
"Multiple password hashing (Lazy)",
("Hashing password '" + pw + "' using Argon2 lazy methods. " +
"This also may take a while...")
)
log()
var i = 0
// In the following while loop, we keep hashing the above password
// then we verify it. If at any point we aren't successful we log it.
while (i < 30) {
try {
// You can also remove the null bytes at the end of this hex hash
// using cryptoPwHashStrRemoveNulls instead of
// cryptoPwHashStr, but that is not recommended
// as Argon2 needs at least one null byte
// at the end.
val hash: String = lazySodium.cryptoPwHashStr(pw, 2, PwHash.MEMLIMIT_MIN)
// To get an Argon2 hash instead of a hex hash,
// lazySodium.str(lazySodium.toBinary(hash)) is one way to do that.
logt("Password hashing successful: $hash")
val result: Boolean = lazySodium.cryptoPwHashStrVerify(hash, pw)
logt("Password hashing verification: $result")
} catch (e: SodiumException) {
logt("Password hashing unsuccessful: " + e.message)
}
i++
}
log()
}
companion object {
@JvmStatic
fun main(args: Array<String>) {
// First setup
setup()
printTitle()
if (args.size == 0) {
printIntro()
} else {
// Run only if provided an argument
val arg1 = args[0]
try {
val parsed = arg1.toInt()
val main = Main(parsed)
main.run()
} catch (e: NumberFormatException) {
AnsiConsole.system_err.println(
("Error: " + arg1 + " is not a valid number. " +
"Please provide a number of the operation you want to perform.")
)
}
}
}
private fun setup() {
AnsiConsole.systemInstall()
}
private fun printTitle() {
val line: Ansi = ansi()
.fgBrightRed()
.a(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
.reset()
log()
log(line)
log(" Lazysodium for Java (Examples) ")
log(line)
log()
}
private fun printIntro() {
log("Please provide, as a command line argument, one of the following numbers:")
log("1. Secret key: Perform encryption using a symmetric key.")
log("2. Public key: Encryption using public-private key.")
log("3. Generic hashing: Hash arbitrarily.")
log("4. Password hashing: Password hash.")
log("5. Sign (detached): Sign a message in detached mode.")
log()
}
// Helpers
private fun log(s: String = "") {
println(s)
}
private fun logt(s: String) {
println("\t" + s)
}
private fun log(s: Ansi) {
AnsiConsole.out().println(s)
}
}
}
================================================
FILE: settings.gradle
================================================
/*
* Copyright (c) Terl Tech Ltd • 14/06/19 17:54 • goterl.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
buildscript {
repositories {
maven {
url 'https://bndtools.jfrog.io/bndtools/libs-snapshot'
}
}
dependencies {
classpath 'biz.aQute.bnd:biz.aQute.bnd.gradle:+'
}
}
rootProject.name = 'lazysodium-java'
include 'sample-app'
================================================
FILE: src/main/java/com/goterl/lazysodium/LazySodium.java
================================================
/*
* Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.goterl.lazysodium;
import com.goterl.lazysodium.exceptions.SodiumException;
import com.goterl.lazysodium.interfaces.*;
import com.goterl.lazysodium.interfaces.Ristretto255.Checker;
import com.goterl.lazysodium.interfaces.Ristretto255.RistrettoPoint;
import com.goterl.lazysodium.utils.*;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import java.math.BigInteger;
import javax.crypto.AEADBadTagException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public abstract class LazySodium implements
Base,
Random,
AEAD.Native, AEAD.Lazy,
GenericHash.Native, GenericHash.Lazy,
ShortHash.Native, ShortHash.Lazy,
SecureMemory.Native, SecureMemory.Lazy,
Auth.Native, Auth.Lazy,
SecretStream.Native, SecretStream.Lazy,
Stream.Native, Stream.Lazy,
Padding.Native, Padding.Lazy,
Helpers.Native, Helpers.Lazy,
PwHash.Native, PwHash.Lazy,
Hash.Native, Hash.Lazy,
Sign.Native, Sign.Lazy,
Box.Native, Box.Lazy,
SecretBox.Native, SecretBox.Lazy,
KeyExchange.Native, KeyExchange.Lazy,
KeyDerivation.Native, KeyDerivation.Lazy,
DiffieHellman.Native, DiffieHellman.Lazy,
Ristretto255.Native, Ristretto255.Lazy {
protected final Charset charset;
protected final MessageEncoder messageEncoder;
public static Base64Facade base64Facade;
public LazySodium() {
this(StandardCharsets.UTF_8, new HexMessageEncoder());
}
public LazySodium(Charset charset) {
this(charset, new HexMessageEncoder());
}
public LazySodium(MessageEncoder messageEncoder) {
this(StandardCharsets.UTF_8, messageEncoder);
}
public LazySodium(Charset charset, MessageEncoder messageEncoder) {
this.charset = charset;
this.messageEncoder = messageEncoder;
}
public static Integer longToInt(long lng) {
if (lng < 0) {
return 0;
}
return Math.toIntExact(lng);
}
//// -------------------------------------------|
//// HELPERS
//// -------------------------------------------|
@Override
public int sodiumInit() {
return getSodium().sodium_init();
}
@Override
public String sodiumBin2Hex(byte[] bin) {
return bytesToHex(bin);
}
@Override
public byte[] sodiumHex2Bin(String hex) {
return hexToBytes(hex);
}
public String toHexStr(byte[] bs) {
return bytesToHex(bs);
}
public byte[] toBinary(String hex) {
return hexToBytes(hex);
}
/**
* Bytes to hexadecimal. Equivalent to {@link #sodiumBin2Hex(byte[])} but static.
*
* @param bin Byte array.
* @return Hexadecimal string.
*/
public static String toHex(byte[] bin) {
return bytesToHex(bin);
}
/**
* Hexadecimal string to bytes. Equivalent to {@link #sodiumHex2Bin(String)}} but static.
*
* @param hex Hexadecimal string to convert to bytes.
* @return Byte array.
*/
public static byte[] toBin(String hex) {
return hexToBytes(hex);
}
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
// The following is from https://stackoverflow.com/a/9855338/3526705
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
// The following is from https://stackoverflow.com/a/140861/3526705
private static byte[] hexToBytes(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i + 1), 16));
}
return data;
}
//// -------------------------------------------|
//// RANDOM
//// -------------------------------------------|
@Override
public long randomBytesRandom() {
return getSodium().randombytes_random();
}
@Override
public byte[] randomBytesBuf(int size) {
byte[] bs = new byte[size];
getSodium().randombytes_buf(bs, size);
return bs;
}
@Override
public byte[] nonce(int size) {
return randomBytesBuf(size);
}
@Override
public long randomBytesUniform(int upperBound) {
return getSodium().randombytes_uniform(upperBound);
}
@Override
public byte[] randomBytesDeterministic(int size, byte[] seed) {
byte[] bs = new byte[size];
getSodium().randombytes_buf_deterministic(bs, size, seed);
return bs;
}
//// -------------------------------------------|
//// PADDING
//// -------------------------------------------|
@Override
public boolean sodiumPad(IntByReference paddedBuffLen, Pointer buf, int unpaddedBufLen, int blockSize, int maxBufLen) {
return successful(getSodium().sodium_pad(paddedBuffLen, buf, unpaddedBufLen, blockSize, maxBufLen));
}
@Override
public boolean sodiumUnpad(IntByReference unPaddedBuffLen, Pointer buf, int paddedBufLen, int blockSize) {
return successful(getSodium().sodium_unpad(unPaddedBuffLen, buf, paddedBufLen, blockSize));
}
//// -------------------------------------------|
//// SECURE MEMORY
//// -------------------------------------------|
@Override
public boolean sodiumMemZero(byte[] pnt, int len) {
return successful(getSodium().sodium_memzero(pnt, len));
}
@Override
public boolean sodiumMLock(byte[] array, int len) {
return successful(getSodium().sodium_mlock(array, len));
}
@Override
public boolean sodiumMUnlock(byte[] array, int len) {
return successful(getSodium().sodium_munlock(array, len));
}
@Override
public Pointer sodiumMalloc(int size) {
return getSodium().sodium_malloc(size);
}
@Override
public Pointer sodiumAllocArray(int count, int size) {
return getSodium().sodium_allocarray(count, size);
}
@Override
public void sodiumFree(Pointer p) {
getSodium().sodium_free(p);
}
@Override
public boolean sodiumMProtectNoAccess(Pointer ptr) {
return successful(getSodium().sodium_mprotect_noaccess(ptr));
}
@Override
public boolean sodiumMProtectReadOnly(Pointer ptr) {
return successful(getSodium().sodium_mprotect_readonly(ptr));
}
@Override
public boolean sodiumMProtectReadWrite(Pointer ptr) {
return successful(getSodium().sodium_mprotect_readwrite(ptr));
}
//// -------------------------------------------|
//// KDF KEYGEN
//// -------------------------------------------|
@Override
public void cryptoKdfKeygen(byte[] masterKey) {
if (masterKey.length != KeyDerivation.MASTER_KEY_BYTES) {
throw new IllegalArgumentException("Master key length is wrong: " + masterKey.length);
}
getSodium().crypto_kdf_keygen(masterKey);
}
@Override
public int cryptoKdfDeriveFromKey(byte[] subKey, int subKeyLen, long subKeyId, byte[] context, byte[] masterKey) {
if (subKeyLen < KeyDerivation.BYTES_MIN || subKeyLen > KeyDerivation.BYTES_MAX) {
throw new IllegalArgumentException("Sub Key Length is out of bounds: " + subKeyLen);
}
if (subKey.length < subKeyLen) {
throw new IllegalArgumentException("Sub Key array is less than specified size");
}
if (context.length != KeyDerivation.CONTEXT_BYTES) {
throw new IllegalArgumentException("Context length is wrong: " + context.length);
}
return getSodium().crypto_kdf_derive_from_key(subKey, subKeyLen, subKeyId, context, masterKey);
}
@Override
public Key cryptoKdfKeygen() {
byte[] masterKey = new byte[KeyDerivation.MASTER_KEY_BYTES];
getSodium().crypto_kdf_keygen(masterKey);
return Key.fromBytes(masterKey);
}
@Override
public Key cryptoKdfDeriveFromKey(int lengthOfSubKey, long subKeyId, String context, Key masterKey)
throws SodiumException {
if (!KeyDerivation.Checker.subKeyIsCorrect(lengthOfSubKey)) {
throw new SodiumException("Subkey is not between the correct lengths.");
}
if (!KeyDerivation.Checker.masterKeyIsCorrect(masterKey.getAsBytes().length)) {
throw new SodiumException("Master key is not the correct length.");
}
if (!KeyDerivation.Checker.contextIsCorrect(bytes(context).length)) {
throw new SodiumException("Context is not the correct length.");
}
byte[] subKey = new byte[lengthOfSubKey];
byte[] contextAsBytes = bytes(context);
byte[] masterKeyAsBytes = masterKey.getAsBytes();
int res = getSodium().crypto_kdf_derive_from_key(
subKey,
lengthOfSubKey,
subKeyId,
contextAsBytes,
masterKeyAsBytes
);
if (!successful(res)) {
throw new SodiumException("Failed kdfDeriveFromKey.");
}
return Key.fromBytes(subKey);
}
//// -------------------------------------------|
//// KEY EXCHANGE
//// -------------------------------------------|
@Override
public boolean cryptoKxKeypair(byte[] publicKey, byte[] secretKey) {
return successful(getSodium().crypto_kx_keypair(publicKey, secretKey));
}
@Override
public boolean cryptoKxSeedKeypair(byte[] publicKey, byte[] secretKey, byte[] seed) {
return successful(getSodium().crypto_kx_seed_keypair(publicKey, secretKey, seed));
}
@Override
public boolean cryptoKxClientSessionKeys(byte[] rx, byte[] tx, byte[] clientPk, byte[] clientSk, byte[] serverPk) {
return successful(getSodium().crypto_kx_client_session_keys(rx, tx, clientPk, clientSk, serverPk));
}
@Override
public boolean cryptoKxServerSessionKeys(byte[] rx, byte[] tx, byte[] serverPk, byte[] serverSk, byte[] clientPk) {
return successful(getSodium().crypto_kx_server_session_keys(rx, tx, serverPk, serverSk, clientPk));
}
// -- Lazy functions
@Override
public KeyPair cryptoKxKeypair() {
byte[] secretKey = randomBytesBuf(KeyExchange.SECRETKEYBYTES);
byte[] publicKey = randomBytesBuf(KeyExchange.PUBLICKEYBYTES);
getSodium().crypto_kx_keypair(publicKey, secretKey);
return new KeyPair(Key.fromBytes(publicKey), Key.fromBytes(secretKey));
}
@Override
public KeyPair cryptoKxKeypair(byte[] seed) {
byte[] secretKey = randomBytesBuf(KeyExchange.SECRETKEYBYTES);
byte[] publicKey = randomBytesBuf(KeyExchange.PUBLICKEYBYTES);
getSodium().crypto_kx_seed_keypair(publicKey, secretKey, seed);
return new KeyPair(Key.fromBytes(publicKey), Key.fromBytes(secretKey));
}
@Override
public SessionPair cryptoKxClientSessionKeys(KeyPair clientKeyPair, KeyPair serverKeyPair) throws SodiumException {
return cryptoKxClientSessionKeys(clientKeyPair.getPublicKey(), clientKeyPair.getSecretKey(), serverKeyPair.getPublicKey());
}
@Override
public SessionPair cryptoKxServerSessionKeys(Key serverPk, Key serverSk, Key clientPk) throws SodiumException {
byte[] rx = new byte[KeyExchange.SESSIONKEYBYTES];
byte[] tx = new byte[KeyExchange.SESSIONKEYBYTES];
if (!cryptoKxServerSessionKeys(rx, tx, serverPk.getAsBytes(), serverSk.getAsBytes(), clientPk.getAsBytes())) {
throw new SodiumException("Failed creating server session keys.");
}
return new SessionPair(rx, tx);
}
@Override
public SessionPair cryptoKxClientSessionKeys(Key clientPk, Key clientSk, Key serverPk) throws SodiumException {
byte[] rx = new byte[KeyExchange.SESSIONKEYBYTES];
byte[] tx = new byte[KeyExchange.SESSIONKEYBYTES];
if (!cryptoKxClientSessionKeys(rx, tx, clientPk.getAsBytes(), clientSk.getAsBytes(), serverPk.getAsBytes())) {
throw new SodiumException("Failed creating client session keys.");
}
return new SessionPair(rx, tx);
}
@Override
public SessionPair cryptoKxServerSessionKeys(KeyPair serverKeyPair, KeyPair clientKeyPair) throws SodiumException {
return cryptoKxServerSessionKeys(serverKeyPair.getPublicKey(), serverKeyPair.getSecretKey(), clientKeyPair.getPublicKey());
}
//// -------------------------------------------|
//// PASSWORD HASHING
//// -------------------------------------------|
@Override
public boolean cryptoPwHash(byte[] outputHash,
int outputHashLen,
byte[] password,
int passwordLen,
byte[] salt,
long opsLimit,
NativeLong memLimit,
PwHash.Alg alg) {
if (outputHashLen < 0 || outputHashLen > outputHash.length) {
throw new IllegalArgumentException("outputHashLen out of bounds: " + outputHashLen);
}
if (passwordLen < 0 || passwordLen > password.length) {
throw new IllegalArgumentException("passwordLen out of bounds: " + passwordLen);
}
int res = getSodium().crypto_pwhash(outputHash,
outputHashLen,
password,
passwordLen,
salt,
opsLimit,
memLimit,
alg.getValue());
return successful(res);
}
@Override
public boolean cryptoPwHashStr(byte[] outputStr,
byte[] password,
int passwordLen,
long opsLimit,
NativeLong memLimit) {
if (passwordLen < 0 || passwordLen > password.length) {
throw new IllegalArgumentException("passwordLen out of bounds: " + passwordLen);
}
int res = getSodium().crypto_pwhash_str(outputStr, password, passwordLen, opsLimit, memLimit);
return successful(res);
}
@Override
public boolean cryptoPwHashStrVerify(byte[] hash, byte[] password, int passwordLen) {
if (passwordLen < 0 || passwordLen > password.length) {
throw new IllegalArgumentException("passwordLen out of bounds: " + passwordLen);
}
return successful(getSodium().crypto_pwhash_str_verify(hash, password, passwordLen));
}
@Override
public boolean cryptoPwHashStrNeedsRehash(byte[] hash, long opsLimit, NativeLong memLimit) {
return successful(getSodium().crypto_pwhash_str_needs_rehash(hash, opsLimit, memLimit));
}
// lazy
@Override
public String cryptoPwHash(String password, int lengthOfHash, byte[] salt, long opsLimit, NativeLong memLimit, PwHash.Alg alg)
throws SodiumException {
byte[] passwordBytes = bytes(password);
PwHash.Checker.checkAll(passwordBytes.length, salt.length, opsLimit, memLimit);
byte[] hash = new byte[lengthOfHash];
int res = getSodium().crypto_pwhash(hash, hash.length, passwordBytes, passwordBytes.length, salt, opsLimit, memLimit, alg.getValue());
if (res != 0) {
throw new SodiumException(
"Could not hash your string. This may be due to insufficient " +
"memory or your CPU does not support Argon2's instruction set."
);
}
return messageEncoder.encode(hash);
}
@Override
public String cryptoPwHashStr(String password, long opsLimit, NativeLong memLimit) throws SodiumException {
byte[] hash = new byte[PwHash.STR_BYTES];
byte[] passwordBytes = bytes(password);
boolean res = cryptoPwHashStr(hash, passwordBytes, passwordBytes.length, opsLimit, memLimit);
if (!res) {
throw new SodiumException("Password hashing failed.");
}
return messageEncoder.encode(hash);
}
@Override
public String cryptoPwHashStrRemoveNulls(String password, long opsLimit, NativeLong memLimit) throws SodiumException {
byte[] hash = new byte[PwHash.STR_BYTES];
byte[] passwordBytes = bytes(password);
boolean res = cryptoPwHashStr(hash, passwordBytes, passwordBytes.length, opsLimit, memLimit);
if (!res) {
throw new SodiumException("Password hashing failed.");
}
byte[] hashNoNulls = removeNulls(hash);
return messageEncoder.encode(hashNoNulls);
}
@Override
public boolean cryptoPwHashStrVerify(String hash, String password) {
byte[] hashBytes = messageEncoder.decode(hash);
byte[] passwordBytes = bytes(password);
// If the end of the hash does not have an null byte,
// let's add it.
byte endOfHash = hashBytes[hashBytes.length - 1];
if (endOfHash != 0) {
byte[] hashWithNullByte = new byte[hashBytes.length + 1];
System.arraycopy(hashBytes, 0, hashWithNullByte, 0, hashBytes.length);
hashBytes = hashWithNullByte;
}
return cryptoPwHashStrVerify(hashBytes, passwordBytes, passwordBytes.length);
}
//// -------------------------------------------|
//// HASH
//// -------------------------------------------|
@Override
public boolean cryptoHashSha256(byte[] out, byte[] in, long inLen) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_hash_sha256(out, in, inLen));
}
@Override
public boolean cryptoHashSha256Init(Hash.State256 state) {
return successful(getSodium().crypto_hash_sha256_init(state));
}
@Override
public boolean cryptoHashSha256Update(Hash.State256 state, byte[] in, long inLen) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_hash_sha256_update(state, in, inLen));
}
@Override
public boolean cryptoHashSha256Final(Hash.State256 state, byte[] out) {
return successful(getSodium().crypto_hash_sha256_final(state, out));
}
@Override
public boolean cryptoHashSha512(byte[] out, byte[] in, long inLen) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_hash_sha512(out, in, inLen));
}
@Override
public boolean cryptoHashSha512Init(Hash.State512 state) {
return successful(getSodium().crypto_hash_sha512_init(state));
}
@Override
public boolean cryptoHashSha512Update(Hash.State512 state, byte[] in, long inLen) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_hash_sha512_update(state, in, inLen));
}
@Override
public boolean cryptoHashSha512Final(Hash.State512 state, byte[] out) {
return successful(getSodium().crypto_hash_sha512_final(state, out));
}
// -- lazy
@Override
public String cryptoHashSha256(String message) throws SodiumException {
byte[] msgBytes = bytes(message);
byte[] hashedBytes = new byte[Hash.SHA256_BYTES];
if (!cryptoHashSha256(hashedBytes, msgBytes, msgBytes.length)) {
throw new SodiumException("Unsuccessful sha-256 hash.");
}
return messageEncoder.encode(hashedBytes);
}
@Override
public String cryptoHashSha512(String message) throws SodiumException {
byte[] msgBytes = bytes(message);
byte[] hashedBytes = new byte[Hash.SHA512_BYTES];
if (!cryptoHashSha512(hashedBytes, msgBytes, msgBytes.length)) {
throw new SodiumException("Unsuccessful sha-512 hash.");
}
return messageEncoder.encode(hashedBytes);
}
@Override
public boolean cryptoHashSha256Update(Hash.State256 state, String messagePart) {
byte[] msgBytes = bytes(messagePart);
return cryptoHashSha256Update(state, msgBytes, msgBytes.length);
}
@Override
public String cryptoHashSha256Final(Hash.State256 state) throws SodiumException {
byte[] finalHash = new byte[Hash.SHA256_BYTES];
if (!cryptoHashSha256Final(state, finalHash)) {
throw new SodiumException("Could not finalise sha-256.");
}
return messageEncoder.encode(finalHash);
}
@Override
public boolean cryptoHashSha512Update(Hash.State512 state, String messagePart) {
byte[] msgBytes = bytes(messagePart);
return cryptoHashSha512Update(state, msgBytes, msgBytes.length);
}
@Override
public String cryptoHashSha512Final(Hash.State512 state) throws SodiumException {
byte[] finalHash = new byte[Hash.SHA512_BYTES];
if (!cryptoHashSha512Final(state, finalHash)) {
throw new SodiumException("Could not finalise sha-512.");
}
return messageEncoder.encode(finalHash);
}
//// -------------------------------------------|
//// SECRET BOX
//// -------------------------------------------|
@Override
public void cryptoSecretBoxKeygen(byte[] key) {
getSodium().crypto_secretbox_keygen(key);
}
@Override
public boolean cryptoSecretBoxEasy(byte[] cipherText, byte[] message, long messageLen, byte[] nonce, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_secretbox_easy(cipherText, message, messageLen, nonce, key));
}
@Override
public boolean cryptoSecretBoxOpenEasy(byte[] message, byte[] cipherText, long cipherTextLen, byte[] nonce, byte[] key) {
if (cipherTextLen < 0 || cipherTextLen > cipherText.length) {
throw new IllegalArgumentException("cipherTextLen out of bounds: " + cipherTextLen);
}
return successful(getSodium().crypto_secretbox_open_easy(message, cipherText, cipherTextLen, nonce, key));
}
@Override
public boolean cryptoSecretBoxDetached(byte[] cipherText, byte[] mac, byte[] message, long messageLen, byte[] nonce, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_secretbox_detached(cipherText, mac, message, messageLen, nonce, key));
}
@Override
public boolean cryptoSecretBoxOpenDetached(byte[] message, byte[] cipherText, byte[] mac, long cipherTextLen, byte[] nonce, byte[] key) {
if (cipherTextLen < 0 || cipherTextLen > cipherText.length) {
throw new IllegalArgumentException("cipherTextLen out of bounds: " + cipherTextLen);
}
return successful(getSodium().crypto_secretbox_open_detached(message, cipherText, mac, cipherTextLen, nonce, key));
}
/// --- Lazy
@Override
public Key cryptoSecretBoxKeygen() {
byte[] key = new byte[SecretBox.KEYBYTES];
cryptoSecretBoxKeygen(key);
return Key.fromBytes(key);
}
@Override
public String cryptoSecretBoxEasy(String message, byte[] nonce, Key key) throws SodiumException {
byte[] keyBytes = key.getAsBytes();
byte[] messageBytes = bytes(message);
byte[] cipherTextBytes = new byte[SecretBox.MACBYTES + messageBytes.length];
if (!cryptoSecretBoxEasy(cipherTextBytes, messageBytes, messageBytes.length, nonce, keyBytes)) {
throw new SodiumException("Could not encrypt message.");
}
return messageEncoder.encode(cipherTextBytes);
}
@Override
public String cryptoSecretBoxOpenEasy(String cipher, byte[] nonce, Key key) throws SodiumException {
byte[] keyBytes = key.getAsBytes();
byte[] cipherBytes = messageEncoder.decode(cipher);
byte[] messageBytes = new byte[cipherBytes.length - SecretBox.MACBYTES];
if (!cryptoSecretBoxOpenEasy(messageBytes, cipherBytes, cipherBytes.length, nonce, keyBytes)) {
throw new SodiumException("Could not decrypt message.");
}
return str(messageBytes);
}
@Override
public DetachedEncrypt cryptoSecretBoxDetached(String message, byte[] nonce, Key key) throws SodiumException {
byte[] keyBytes = key.getAsBytes();
byte[] messageBytes = bytes(message);
byte[] cipherTextBytes = new byte[messageBytes.length];
byte[] macBytes = new byte[SecretBox.MACBYTES];
if (!cryptoSecretBoxDetached(cipherTextBytes, macBytes, messageBytes, messageBytes.length, nonce, keyBytes)) {
throw new SodiumException("Could not encrypt detached message.");
}
return new DetachedEncrypt(cipherTextBytes, macBytes);
}
@Override
public String cryptoSecretBoxOpenDetached(DetachedEncrypt cipherAndMac, byte[] nonce, Key key) throws SodiumException {
byte[] keyBytes = key.getAsBytes();
byte[] cipherBytes = cipherAndMac.getCipher();
byte[] macBytes = cipherAndMac.getMac();
byte[] messageBytes = new byte[cipherBytes.length];
if (!cryptoSecretBoxOpenDetached(messageBytes, cipherBytes, macBytes, cipherBytes.length, nonce, keyBytes)) {
throw new SodiumException("Could not decrypt detached message.");
}
return str(messageBytes);
}
//// -------------------------------------------|
//// DIFFIE HELLMAN
//// -------------------------------------------|
@Override
public boolean cryptoScalarMultBase(byte[] publicKey, byte[] secretKey) {
return successful(getSodium().crypto_scalarmult_base(publicKey, secretKey));
}
@Override
public Key cryptoScalarMultBase(Key secretKey) {
byte[] publicKey = new byte[DiffieHellman.SCALARMULT_BYTES];
cryptoScalarMultBase(publicKey, secretKey.getAsBytes());
return Key.fromBytes(publicKey);
}
@Override
public boolean cryptoScalarMult(byte[] shared, byte[] secretKey, byte[] publicKey) {
return successful(getSodium().crypto_scalarmult(shared, secretKey, publicKey));
}
@Override
public Key cryptoScalarMult(Key secretKey, Key publicKey) {
byte[] sharedKey = new byte[DiffieHellman.SCALARMULT_BYTES];
cryptoScalarMult(sharedKey, secretKey.getAsBytes(), publicKey.getAsBytes());
return Key.fromBytes(sharedKey);
}
// -------------------------------------------|
//// CRYPTO BOX
//// -------------------------------------------|
@Override
public boolean cryptoBoxKeypair(byte[] publicKey, byte[] secretKey) {
return successful(getSodium().crypto_box_keypair(publicKey, secretKey));
}
@Override
public boolean cryptoBoxSeedKeypair(byte[] publicKey, byte[] secretKey, byte[] seed) {
return successful(getSodium().crypto_box_seed_keypair(publicKey, secretKey, seed));
}
@Override
public boolean cryptoBoxEasy(byte[] cipherText, byte[] message, long messageLen, byte[] nonce, byte[] publicKey, byte[] secretKey) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_box_easy(cipherText, message, messageLen, nonce, publicKey, secretKey));
}
@Override
public boolean cryptoBoxOpenEasy(byte[] message, byte[] cipherText, long cipherTextLen, byte[] nonce, byte[] publicKey, byte[] secretKey) {
if (cipherTextLen < 0 || cipherTextLen > cipherText.length) {
throw new IllegalArgumentException("cipherTextLen out of bounds: " + cipherTextLen);
}
return successful(getSodium().crypto_box_open_easy(message, cipherText, cipherTextLen, nonce, publicKey, secretKey));
}
@Override
public boolean cryptoBoxDetached(byte[] cipherText, byte[] mac, byte[] message, long messageLen, byte[] nonce, byte[] publicKey, byte[] secretKey) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_box_detached(cipherText, mac, message, messageLen, nonce, publicKey, secretKey));
}
@Override
public boolean cryptoBoxOpenDetached(byte[] message, byte[] cipherText, byte[] mac, long cipherTextLen, byte[] nonce, byte[] publicKey, byte[] secretKey) {
if (cipherTextLen < 0 || cipherTextLen > cipherText.length) {
throw new IllegalArgumentException("cipherTextLen out of bounds: " + cipherTextLen);
}
return successful(getSodium().crypto_box_open_detached(message, cipherText, mac, cipherTextLen, nonce, publicKey, secretKey));
}
@Override
public boolean cryptoBoxBeforeNm(byte[] k, byte[] publicKey, byte[] secretKey) {
return successful(getSodium().crypto_box_beforenm(k, publicKey, secretKey));
}
@Override
public boolean cryptoBoxEasyAfterNm(byte[] cipherText, byte[] message, long messageLen, byte[] nonce, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_box_easy_afternm(cipherText, message, messageLen, nonce, key));
}
@Override
public boolean cryptoBoxOpenEasyAfterNm(byte[] message, byte[] cipher, long cLen, byte[] nonce, byte[] key) {
if (cLen < 0 || cLen > cipher.length) {
throw new IllegalArgumentException("cLen out of bounds: " + cLen);
}
return successful(getSodium().crypto_box_open_easy_afternm(message, cipher, cLen, nonce, key));
}
@Override
public boolean cryptoBoxDetachedAfterNm(byte[] cipherText, byte[] mac, byte[] message, long messageLen, byte[] nonce, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_box_detached_afternm(cipherText, mac, message, messageLen, nonce, key));
}
@Override
public boolean cryptoBoxOpenDetachedAfterNm(byte[] message, byte[] cipherText, byte[] mac, long cipherTextLen, byte[] nonce, byte[] key) {
if (cipherTextLen < 0 || cipherTextLen > cipherText.length) {
throw new IllegalArgumentException("cipherTextLen out of bounds: " + cipherTextLen);
}
return successful(getSodium().crypto_box_open_detached_afternm(message, cipherText, mac, cipherTextLen, nonce, key));
}
@Override
public boolean cryptoBoxSeal(byte[] cipher, byte[] message, long messageLen, byte[] publicKey) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_box_seal(cipher, message, messageLen, publicKey));
}
@Override
public boolean cryptoBoxSealOpen(byte[] m, byte[] cipher, long cipherLen, byte[] publicKey, byte[] secretKey) {
if (cipherLen < 0 || cipherLen > cipher.length) {
throw new IllegalArgumentException("cipherLen out of bounds: " + cipherLen);
}
return successful(getSodium().crypto_box_seal_open(m, cipher, cipherLen, publicKey, secretKey));
}
// -- lazy
@Override
public KeyPair cryptoBoxKeypair() throws SodiumException {
byte[] publicKey = randomBytesBuf(Box.PUBLICKEYBYTES);
byte[] secretKey = randomBytesBuf(Box.SECRETKEYBYTES);
if (!cryptoBoxKeypair(publicKey, secretKey)) {
throw new SodiumException("Unable to create a public and private key.");
}
return new KeyPair(Key.fromBytes(publicKey), Key.fromBytes(secretKey));
}
@Override
public KeyPair cryptoBoxSeedKeypair(byte[] seed) throws SodiumException {
byte[] publicKey = randomBytesBuf(Box.PUBLICKEYBYTES);
byte[] secretKey = randomBytesBuf(Box.SECRETKEYBYTES);
if (!Box.Checker.checkSeed(seed.length)) {
throw new SodiumException("Seed is incorrect size.");
}
if (!cryptoBoxSeedKeypair(publicKey, secretKey, seed)) {
throw new SodiumException("Unable to create a public and private key.");
}
return new KeyPair(Key.fromBytes(publicKey), Key.fromBytes(secretKey));
}
@Override
public String cryptoBoxEasy(String message, byte[] nonce, KeyPair keyPair) throws SodiumException {
byte[] messageBytes = bytes(message);
byte[] cipherBytes = new byte[Box.MACBYTES + messageBytes.length];
boolean res = cryptoBoxEasy(
cipherBytes,
messageBytes,
messageBytes.length,
nonce,
keyPair.getPublicKey().getAsBytes(),
keyPair.getSecretKey().getAsBytes()
);
if (!res) {
throw new SodiumException("Could not encrypt your message.");
}
return messageEncoder.encode(cipherBytes);
}
@Override
public String cryptoBoxOpenEasy(String cipherText, byte[] nonce, KeyPair keyPair) throws SodiumException {
byte[] cipher = messageEncoder.decode(cipherText);
byte[] message = new byte[cipher.length - Box.MACBYTES];
boolean res =
cryptoBoxOpenEasy(
message,
cipher,
cipher.length,
nonce,
keyPair.getPublicKey().getAsBytes(),
keyPair.getSecretKey().getAsBytes()
);
if (!res) {
throw new SodiumException("Could not decrypt your message.");
}
return str(message);
}
@Override
public String cryptoBoxBeforeNm(byte[] publicKey, byte[] secretKey) throws SodiumException {
byte[] sharedKey = new byte[Box.BEFORENMBYTES];
if (!Box.Checker.checkPublicKey(publicKey.length)) {
throw new SodiumException("Public key length is incorrect.");
}
if (!Box.Checker.checkSecretKey(secretKey.length)) {
throw new SodiumException("Secret key length is incorrect.");
}
boolean res = cryptoBoxBeforeNm(sharedKey, publicKey, secretKey);
if (!res) {
throw new SodiumException("Unable to encrypt using shared secret key.");
}
return messageEncoder.encode(sharedKey);
}
@Override
public String cryptoBoxBeforeNm(KeyPair keyPair) throws SodiumException {
return cryptoBoxBeforeNm(keyPair.getPublicKey().getAsBytes(), keyPair.getSecretKey().getAsBytes());
}
@Override
public String cryptoBoxEasyAfterNm(String message, byte[] nonce, String sharedSecretKey) throws SodiumException {
if (!Box.Checker.checkNonce(nonce.length)) {
throw new SodiumException("Incorrect nonce length.");
}
byte[] sharedKey = messageEncoder.decode(sharedSecretKey);
if (!Box.Checker.checkBeforeNmBytes(sharedKey.length)) {
throw new SodiumException("Incorrect shared secret key length.");
}
byte[] messageBytes = bytes(message);
byte[] cipher = new byte[messageBytes.length + Box.MACBYTES];
boolean res = cryptoBoxEasyAfterNm(cipher, messageBytes, messageBytes.length, nonce, sharedKey);
if (!res) {
throw new SodiumException("Could not fully complete shared secret key encryption.");
}
return messageEncoder.encode(cipher);
}
@Override
public String cryptoBoxOpenEasyAfterNm(String cipher, byte[] nonce, String sharedSecretKey) throws SodiumException {
if (!Box.Checker.checkNonce(nonce.length)) {
throw new SodiumException("Incorrect nonce length.");
}
byte[] sharedKey = messageEncoder.decode(sharedSecretKey);
if (!Box.Checker.checkBeforeNmBytes(sharedKey.length)) {
throw new SodiumException("Incorrect shared secret key length.");
}
byte[] cipherBytes = messageEncoder.decode(cipher);
byte[] message = new byte[cipherBytes.length - Box.MACBYTES];
boolean res = cryptoBoxOpenEasyAfterNm(message, cipherBytes, cipherBytes.length, nonce, sharedKey);
if (!res) {
throw new SodiumException("Could not fully complete shared secret key decryption.");
}
return str(message);
}
@Override
public DetachedEncrypt cryptoBoxDetachedAfterNm(String message, byte[] nonce, String sharedSecretKey) throws SodiumException {
if (!Box.Checker.checkNonce(nonce.length)) {
throw new SodiumException("Incorrect nonce length.");
}
byte[] sharedKey = messageEncoder.decode(sharedSecretKey);
if (!Box.Checker.checkBeforeNmBytes(sharedKey.length)) {
throw new SodiumException("Incorrect shared secret key length.");
}
byte[] messageBytes = bytes(message);
byte[] cipher = new byte[messageBytes.length];
byte[] mac = new byte[Box.MACBYTES];
boolean res = cryptoBoxDetachedAfterNm(cipher, mac, messageBytes, messageBytes.length, nonce, sharedKey);
if (!res) {
throw new SodiumException("Could not fully complete shared secret key detached encryption.");
}
return new DetachedEncrypt(cipher, mac);
}
@Override
public DetachedDecrypt cryptoBoxOpenDetachedAfterNm(DetachedEncrypt detachedEncrypt, byte[] nonce, String sharedSecretKey) throws SodiumException {
if (!Box.Checker.checkNonce(nonce.length)) {
throw new SodiumException("Incorrect nonce length.");
}
byte[] sharedKey = messageEncoder.decode(sharedSecretKey);
if (!Box.Checker.checkBeforeNmBytes(sharedKey.length)) {
throw new SodiumException("Incorrect shared secret key length.");
}
byte[] cipherBytes = detachedEncrypt.getCipher();
byte[] mac = detachedEncrypt.getMac();
byte[] message = new byte[cipherBytes.length];
boolean res = cryptoBoxOpenDetachedAfterNm(message, cipherBytes, mac, cipherBytes.length, nonce, sharedKey);
if (!res) {
throw new SodiumException("Could not fully complete shared secret key detached decryption.");
}
return new DetachedDecrypt(message, mac);
}
@Override
public String cryptoBoxSealEasy(String message, Key publicKey) throws SodiumException {
byte[] keyBytes = publicKey.getAsBytes();
byte[] messageBytes = bytes(message);
byte[] cipher = new byte[Box.SEALBYTES + messageBytes.length];
if (!cryptoBoxSeal(cipher, messageBytes, messageBytes.length, keyBytes)) {
throw new SodiumException("Could not encrypt message.");
}
return messageEncoder.encode(cipher);
}
@Override
public String cryptoBoxSealOpenEasy(String cipherText, KeyPair keyPair) throws SodiumException {
byte[] cipher = messageEncoder.decode(cipherText);
byte[] message = new byte[cipher.length - Box.SEALBYTES];
boolean res = cryptoBoxSealOpen(message,
cipher,
cipher.length,
keyPair.getPublicKey().getAsBytes(),
keyPair.getSecretKey().getAsBytes());
if (!res) {
throw new SodiumException("Could not decrypt your message.");
}
return str(message);
}
//// -------------------------------------------|
//// CRYPTO SIGN
//// -------------------------------------------|
@Override
public boolean cryptoSignInit(Sign.StateCryptoSign state) {
return successful(getSodium().crypto_sign_init(state));
}
@Override
public boolean cryptoSignUpdate(Sign.StateCryptoSign state, byte[] chunk, long chunkLength) {
return successful(getSodium().crypto_sign_update(state, chunk, chunkLength));
}
@Override
public boolean cryptoSignFinalCreate(Sign.StateCryptoSign state, byte[] sig, Pointer sigLen, byte[] sk) {
return successful(getSodium().crypto_sign_final_create(state, sig, sigLen, sk));
}
@Override
public boolean cryptoSignFinalVerify(Sign.StateCryptoSign state, byte[] sig, byte[] pk) {
return successful(getSodium().crypto_sign_final_verify(state, sig, pk));
}
@Override
public boolean cryptoSignKeypair(byte[] publicKey, byte[] secretKey) {
return successful(getSodium().crypto_sign_keypair(publicKey, secretKey));
}
@Override
public boolean cryptoSignSeedKeypair(byte[] publicKey, byte[] secretKey, byte[] seed) {
return successful(getSodium().crypto_sign_seed_keypair(publicKey, secretKey, seed));
}
@Override
public boolean cryptoSign(byte[] signedMessage, byte[] message, long messageLen, byte[] secretKey) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_sign(signedMessage, (new PointerByReference(Pointer.NULL)).getPointer(), message, messageLen, secretKey));
}
@Override
public boolean cryptoSignOpen(byte[] message, byte[] signedMessage, long signedMessageLen, byte[] publicKey) {
if (signedMessageLen < 0 || signedMessageLen > signedMessage.length) {
throw new IllegalArgumentException("signedMessageLen out of bounds: " + signedMessageLen);
}
return successful(getSodium().crypto_sign_open(message, (new PointerByReference(Pointer.NULL)).getPointer(), signedMessage, signedMessageLen, publicKey));
}
@Override
public boolean cryptoSignDetached(byte[] signature, byte[] message, long messageLen, byte[] secretKey) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_sign_detached(signature, (new PointerByReference(Pointer.NULL)).getPointer(), message, messageLen, secretKey));
}
@Override
public boolean cryptoSignVerifyDetached(byte[] signature, byte[] message, int messageLen, byte[] publicKey) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_sign_verify_detached(signature, message, messageLen, publicKey));
}
@Override
public boolean convertPublicKeyEd25519ToCurve25519(byte[] curve, byte[] ed) {
return successful(getSodium().crypto_sign_ed25519_pk_to_curve25519(curve, ed));
}
@Override
public boolean convertSecretKeyEd25519ToCurve25519(byte[] curve, byte[] ed) {
return successful(getSodium().crypto_sign_ed25519_sk_to_curve25519(curve, ed));
}
@Override
public boolean cryptoSignEd25519SkToSeed(byte[] seed, byte[] ed) {
return successful(getSodium().crypto_sign_ed25519_sk_to_seed(seed, ed));
}
@Override
public boolean cryptoSignEd25519SkToPk(byte[] publicKey, byte[] ed) {
return successful(getSodium().crypto_sign_ed25519_sk_to_pk(publicKey, ed));
}
// -- lazy
@Override
public KeyPair cryptoSignKeypair() throws SodiumException {
byte[] publicKey = randomBytesBuf(Sign.PUBLICKEYBYTES);
byte[] secretKey = randomBytesBuf(Sign.SECRETKEYBYTES);
if (!cryptoSignKeypair(publicKey, secretKey)) {
throw new SodiumException("Could not generate a signing keypair.");
}
return new KeyPair(Key.fromBytes(publicKey), Key.fromBytes(secretKey));
}
@Override
public KeyPair cryptoSignSeedKeypair(byte[] seed) throws SodiumException {
byte[] publicKey = randomBytesBuf(Sign.PUBLICKEYBYTES);
byte[] secretKey = randomBytesBuf(Sign.SECRETKEYBYTES);
if (!cryptoSignSeedKeypair(publicKey, secretKey, seed)) {
throw new SodiumException("Could not generate a signing keypair with a seed.");
}
return new KeyPair(Key.fromBytes(publicKey), Key.fromBytes(secretKey));
}
@Override
public KeyPair cryptoSignSecretKeyPair(Key secretKey) throws SodiumException {
byte[] publicKey = new byte[Sign.PUBLICKEYBYTES];
byte[] secKeyBytes = secretKey.getAsBytes();
if (!cryptoSignEd25519SkToPk(publicKey, secKeyBytes)) {
throw new SodiumException("Could not extract public key.");
}
return new KeyPair(Key.fromBytes(publicKey), Key.fromBytes(secKeyBytes));
}
@Override
public String cryptoSign(String message, String secretKey) throws SodiumException {
byte[] messageBytes = bytes(message);
byte[] secretKeyBytes = messageEncoder.decode(secretKey);
byte[] signedMessage = randomBytesBuf(Sign.BYTES + messageBytes.length);
boolean res = cryptoSign(signedMessage, messageBytes, messageBytes.length, secretKeyBytes);
if (!res) {
throw new SodiumException("Could not sign your message.");
}
return messageEncoder.encode(signedMessage);
}
@Override
public String cryptoSign(String message, Key secretKey) throws SodiumException {
return cryptoSign(message, secretKey.getAsHexString());
}
@Override
public String cryptoSignOpen(String signedMessage, Key publicKey) {
byte[] signedMessageBytes = messageEncoder.decode(signedMessage);
byte[] publicKeyBytes = publicKey.getAsBytes();
byte[] messageBytes = randomBytesBuf(signedMessageBytes.length - Sign.BYTES);
boolean res = cryptoSignOpen(
messageBytes,
signedMessageBytes,
signedMessageBytes.length,
publicKeyBytes
);
if (!res) {
return null;
}
return str(messageBytes);
}
@Override
public String cryptoSignDetached(String message, Key secretKey) throws SodiumException {
byte[] messageBytes = bytes(message);
byte[] skBytes = secretKey.getAsBytes();
byte[] signatureBytes = new byte[Sign.BYTES];
if (!cryptoSignDetached(signatureBytes, messageBytes, messageBytes.length, skBytes)) {
throw new SodiumException("Could not create a signature for your message in detached mode.");
}
return messageEncoder.encode(signatureBytes);
}
@Override
public boolean cryptoSignVerifyDetached(String signature, String message, Key publicKey) {
byte[] messageBytes = bytes(message);
byte[] pkBytes = publicKey.getAsBytes();
byte[] signatureBytes = messageEncoder.decode(signature);
return cryptoSignVerifyDetached(signatureBytes, messageBytes, messageBytes.length, pkBytes);
}
@Override
public KeyPair convertKeyPairEd25519ToCurve25519(KeyPair ed25519KeyPair) throws SodiumException {
byte[] edPkBytes = ed25519KeyPair.getPublicKey().getAsBytes();
byte[] edSkBytes = ed25519KeyPair.getSecretKey().getAsBytes();
byte[] curvePkBytes = new byte[Sign.CURVE25519_PUBLICKEYBYTES];
byte[] curveSkBytes = new byte[Sign.CURVE25519_SECRETKEYBYTES];
boolean pkSuccess = convertPublicKeyEd25519ToCurve25519(curvePkBytes, edPkBytes);
boolean skSuccess = convertSecretKeyEd25519ToCurve25519(curveSkBytes, edSkBytes);
if (!pkSuccess || !skSuccess) {
throw new SodiumException("Could not convert this key pair.");
}
return new KeyPair(Key.fromBytes(curvePkBytes), Key.fromBytes(curveSkBytes));
}
//// -------------------------------------------|
//// SECRET SCREAM
//// -------------------------------------------|
@Override
public void cryptoSecretStreamKeygen(byte[] key) {
getSodium().crypto_secretstream_xchacha20poly1305_keygen(key);
}
@Override
public boolean cryptoSecretStreamInitPush(SecretStream.State state, byte[] header, byte[] key) {
return successful(getSodium().crypto_secretstream_xchacha20poly1305_init_push(state, header, key));
}
@Override
public boolean cryptoSecretStreamPush(SecretStream.State state, byte[] cipher, long[] cipherAddr, byte[] message, long messageLen, byte tag) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_secretstream_xchacha20poly1305_push(
state,
cipher,
cipherAddr,
message,
messageLen,
new byte[0],
0L,
tag
));
}
@Override
public boolean cryptoSecretStreamPush(SecretStream.State state,
byte[] cipher,
byte[] message,
long messageLen,
byte tag) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_secretstream_xchacha20poly1305_push(
state,
cipher,
null,
message,
messageLen,
new byte[0],
0L,
tag
));
}
@Override
public boolean cryptoSecretStreamPush(SecretStream.State state,
byte[] cipher,
long[] cipherAddr,
byte[] message,
long messageLen,
byte[] additionalData,
long additionalDataLen,
byte tag) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
if (additionalDataLen < 0 || additionalDataLen > additionalData.length) {
throw new IllegalArgumentException("additionalDataLen out of bounds: " + additionalDataLen);
}
return successful(getSodium().crypto_secretstream_xchacha20poly1305_push(
state,
cipher,
cipherAddr,
message,
messageLen,
additionalData,
additionalDataLen,
tag
));
}
@Override
public boolean cryptoSecretStreamInitPull(SecretStream.State state, byte[] header, byte[] key) {
return successful(getSodium().crypto_secretstream_xchacha20poly1305_init_pull(state, header, key));
}
@Override
public boolean cryptoSecretStreamPull(SecretStream.State state,
byte[] message,
long[] messageAddress,
byte[] tag,
byte[] cipher,
long cipherLen,
byte[] additionalData,
long additionalDataLen) {
if (cipherLen < 0 || cipherLen > cipher.length) {
throw new IllegalArgumentException("cipherLen out of bounds: " + cipherLen);
}
if (additionalDataLen < 0 || additionalDataLen > additionalData.length) {
throw new IllegalArgumentException("additionalDataLen out of bounds: " + additionalDataLen);
}
return successful(getSodium().crypto_secretstream_xchacha20poly1305_pull(
state, message, messageAddress, tag, cipher, cipherLen, additionalData, additionalDataLen
));
}
@Override
public boolean cryptoSecretStreamPull(SecretStream.State state, byte[] message, byte[] tag, byte[] cipher, long cipherLen) {
if (cipherLen < 0 || cipherLen > cipher.length) {
throw new IllegalArgumentException("cipherLen out of bounds: " + cipherLen);
}
return successful(getSodium().crypto_secretstream_xchacha20poly1305_pull(
state,
message,
new long[1],
tag,
cipher,
cipherLen,
new byte[0],
0L
));
}
@Override
public Key cryptoSecretStreamKeygen() {
byte[] key = randomBytesBuf(SecretStream.KEYBYTES);
getSodium().crypto_secretstream_xchacha20poly1305_keygen(key);
return Key.fromBytes(key);
}
@Override
public SecretStream.State cryptoSecretStreamInitPush(byte[] header, Key key) throws SodiumException {
SecretStream.State state = new SecretStream.State.ByReference();
if (!SecretStream.Checker.headerCheck(header.length)) {
throw new SodiumException("Header of secret stream incorrect length.");
}
getSodium().crypto_secretstream_xchacha20poly1305_init_push(state, header, key.getAsBytes());
return state;
}
@Override
public String cryptoSecretStreamPush(SecretStream.State state, String message, byte tag) throws SodiumException {
byte[] messageBytes = bytes(message);
byte[] cipher = new byte[SecretStream.ABYTES + messageBytes.length];
int res = getSodium().crypto_secretstream_xchacha20poly1305_push(
state,
cipher,
null,
messageBytes,
messageBytes.length,
new byte[0],
0L,
tag
);
if (res != 0) {
throw new SodiumException("Error when encrypting a message using secret stream.");
}
return messageEncoder.encode(cipher);
}
@Override
public SecretStream.State cryptoSecretStreamInitPull(byte[] header, Key key) throws SodiumException {
SecretStream.State state = new SecretStream.State.ByReference();
if (!SecretStream.Checker.headerCheck(header.length)) {
throw new SodiumException("Header of secret stream incorrect length.");
}
int res = getSodium().crypto_secretstream_xchacha20poly1305_init_pull(state, header, key.getAsBytes());
if (res != 0) {
throw new SodiumException("Could not initialise a decryption state.");
}
return state;
}
@Override
public String cryptoSecretStreamPull(SecretStream.State state, String cipher, byte[] tag) throws SodiumException {
byte[] cipherBytes = messageEncoder.decode(cipher);
byte[] message = new byte[cipherBytes.length - SecretStream.ABYTES];
int res = getSodium().crypto_secretstream_xchacha20poly1305_pull(
state,
message,
null,
tag,
cipherBytes,
cipherBytes.length,
new byte[0],
0L
);
if (res != 0) {
throw new SodiumException("Error when decrypting a message using secret stream.");
}
return str(message);
}
@Override
public void cryptoSecretStreamRekey(SecretStream.State state) {
getSodium().crypto_secretstream_xchacha20poly1305_rekey(state);
}
//// -------------------------------------------|
//// STREAM
//// -------------------------------------------|
@Override
public void cryptoStreamChaCha20Keygen(byte[] key) {
getSodium().crypto_stream_chacha20_keygen(key);
}
@Override
public boolean cryptoStreamChaCha20(byte[] c, long cLen, byte[] nonce, byte[] key) {
if (cLen < 0 || cLen > c.length) {
throw new IllegalArgumentException("cLen out of bounds: " + cLen);
}
return successful(getSodium().crypto_stream_chacha20(c, cLen, nonce, key));
}
@Override
public boolean cryptoStreamChaCha20Xor(byte[] cipher, byte[] message, long messageLen, byte[] nonce, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_stream_chacha20_xor(cipher, message, messageLen, nonce, key));
}
@Override
public boolean cryptoStreamChacha20XorIc(byte[] cipher, byte[] message, long messageLen, byte[] nonce, long ic, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_stream_chacha20_xor_ic(cipher, message, messageLen, nonce, ic, key));
}
// Chacha20 Ietf
@Override
public void cryptoStreamChaCha20IetfKeygen(byte[] key) {
getSodium().crypto_stream_chacha20_ietf_keygen(key);
}
@Override
public boolean cryptoStreamChaCha20Ietf(byte[] c, long cLen, byte[] nonce, byte[] key) {
if (cLen < 0 || cLen > c.length) {
throw new IllegalArgumentException("cLen out of bounds: " + cLen);
}
return successful(getSodium().crypto_stream_chacha20_ietf(c, cLen, nonce, key));
}
@Override
public boolean cryptoStreamChaCha20IetfXor(byte[] cipher, byte[] message, long messageLen, byte[] nonce, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_stream_chacha20_ietf_xor(cipher, message, messageLen, nonce, key));
}
@Override
public boolean cryptoStreamChacha20IetfXorIc(byte[] cipher, byte[] message, long messageLen, byte[] nonce, long ic, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_stream_chacha20_ietf_xor_ic(cipher, message, messageLen, nonce, ic, key));
}
// Salsa20
@Override
public void cryptoStreamSalsa20Keygen(byte[] key) {
getSodium().crypto_stream_salsa20_keygen(key);
}
@Override
public boolean cryptoStreamSalsa20(byte[] c, long cLen, byte[] nonce, byte[] key) {
if (cLen < 0 || cLen > c.length) {
throw new IllegalArgumentException("cLen out of bounds: " + cLen);
}
return successful(getSodium().crypto_stream_salsa20(c, cLen, nonce, key));
}
@Override
public boolean cryptoStreamSalsa20Xor(byte[] cipher, byte[] message, long messageLen, byte[] nonce, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_stream_salsa20_xor(cipher, message, messageLen, nonce, key));
}
@Override
public boolean cryptoStreamSalsa20XorIc(byte[] cipher, byte[] message, long messageLen, byte[] nonce, long ic, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_stream_salsa20_xor_ic(cipher, message, messageLen, nonce, ic, key));
}
@Override
public void cryptoStreamXSalsa20Keygen(byte[] key) {
getSodium().crypto_stream_keygen(key);
}
@Override
public boolean cryptoStreamXSalsa20(byte[] c, long cLen, byte[] nonce, byte[] key) {
if (cLen < 0 || cLen > c.length) {
throw new IllegalArgumentException("cLen out of bounds: " + cLen);
}
return successful(getSodium().crypto_stream(c, cLen, nonce, key));
}
@Override
public boolean cryptoStreamXSalsa20Xor(byte[] cipher, byte[] message, long messageLen, byte[] nonce, byte[] key) {
if (messageLen < 0 || messageLen > message.length) {
throw new IllegalArgumentException("messageLen out of bounds: " + messageLen);
}
return successful(getSodium().crypto_stream_xor(cipher, message, messageLen, nonce, key));
}
// Lazy
@Override
public Key cryptoStreamKeygen(Stream.Method method) {
if (method.equals(Stream.Method.CHACHA20)) {
byte[] k = randomBytesBuf(Stream.CHACHA20_KEYBYTES);
cryptoStreamChaCha20Keygen(k);
return Key.fromBytes(k);
} else if (method.equals(Stream.Method.CHACHA20_IETF)) {
byte[] k = randomBytesBuf(Stream.CHACHA20_IETF_KEYBYTES);
cryptoStreamChaCha20Keygen(k);
return Key.fromBytes(k);
} else if (method.equals(Stream.Method.SALSA20)) {
byte[] k = randomBytesBuf(Stream.SALSA20_KEYBYTES);
cryptoStreamSalsa20Keygen(k);
return Key.fromBytes(k);
} else {
byte[] k = randomBytesBuf(Stream.XSALSA20_KEYBYTES);
cryptoStreamXSalsa20Keygen(k);
return Key.fromBytes(k);
}
}
@Override
public byte[] cryptoStream(byte[] nonce, Key key, Stream.Method method) {
byte[] c = new byte[20];
int cLen = c.length;
if (method.equals(Stream.Method.CHACHA20)) {
cryptoStreamChaCha20(c, cLen, nonce, key.getAsBytes());
} else if (method.equals(Stream.Method.CHACHA20_IETF)) {
cryptoStreamChaCha20Ietf(c, cLen, nonce, key.getAsBytes());
} else if (method.equals(Stream.Method.SALSA20)) {
cryptoStreamSalsa20(c, cLen, nonce, key.getAsBytes());
} else {
cryptoStreamXSalsa20(c, cLen, nonce, key.getAsBytes());
}
return c;
}
@Override
public String cryptoStreamXor(String message, byte[] nonce, Key key, Stream.Method method) {
byte[] mBytes = bytes(message);
return messageEncoder.encode(cryptoStreamDefaultXor(mBytes, nonce, key, method));
}
@Override
public String cryptoStreamXorDecrypt(String cipher, byte[] nonce, Key key, Stream.Method method) {
return str(cryptoStreamDefaultXor(messageEncoder.decode(cipher), nonce, key, method));
}
@Override
public String cryptoStreamXorIc(String message, byte[] nonce, long ic, Key key, Stream.Method method) {
byte[] mBytes = bytes(message);
return messageEncoder.encode(cryptoStreamDefaultXorIc(mBytes, nonce, ic, key, method));
}
@Override
public String cryptoStreamXorIcDecrypt(String cipher, byte[] nonce, long ic, Key key, Stream.Method method) {
byte[] cipherBytes = messageEncoder.decode(cipher);
return str(cryptoStreamDefaultXorIc(cipherBytes, nonce, ic, key, method));
}
private byte[] cryptoStreamDefaultXor(byte[] messageBytes, byte[] nonce, Key key, Stream.Method method) {
int mLen = messageBytes.length;
byte[] cipher = new byte[mLen];
if (method.equals(Stream.Method.CHACHA20)) {
cryptoStreamChaCha20Xor(cipher, messageBytes, mLen, nonce, key.getAsBytes());
} else if (method.equals(Stream.Method.CHACHA20_IETF)) {
cryptoStreamChaCha20IetfXor(cipher, messageBytes, mLen, nonce, key.getAsBytes());
} else if (method.equals(Stream.Method.SALSA20)) {
cryptoStreamSalsa20Xor(cipher, messageBytes, mLen, nonce, key.getAsBytes());
} else {
cryptoStreamXSalsa20Xor(cipher, messageBytes, mLen, nonce, key.getAsBytes());
}
return cipher;
}
protected byte[] cryptoStreamDefaultXorIc(byte[] messageBytes, byte[] nonce, long ic, Key key, Stream.Method method) {
int mLen = messageBytes.length;
byte[] cipher = new byte[mLen];
if (method.equals(Stream.Method.CHACHA20)) {
cryptoStreamChacha20XorIc(cipher, messageBytes, mLen, nonce, ic, key.getAsBytes());
} else if (method.equals(Stream.Method.CHACHA20_IETF)) {
cryptoStreamChacha20IetfXorIc(cipher, messageBytes, mLen, nonce, ic, key.getAsBytes());
} else if (method.equals(Stream.Method.SALSA20)) {
cryptoStreamSalsa20XorIc(cipher, messageBytes, mLen, nonce, ic, key.getAsBytes());
} else {
// XSalsa20 has no IC so return the
// one without the IC
cryptoStreamXSalsa20Xor(cipher, messageBytes, mLen, nonce, key.getAsBytes());
}
return cipher;
}
//// -------------------------------------------|
//// CRYPTO AUTH
//// -------------------------------------------|
@Override
public boolean cryptoAuth(byte[] tag, byte[] in, long inLen, byte[] key) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth(tag, in, inLen, key));
}
@Override
public boolean cryptoAuthVerify(byte[] tag, byte[] in, long inLen, byte[] key) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth_verify(tag, in, inLen, key));
}
@Override
public void cryptoAuthKeygen(byte[] k) {
getSodium().crypto_auth_keygen(k);
}
@Override
public Key cryptoAuthKeygen() {
byte[] key = randomBytesBuf(Auth.KEYBYTES);
cryptoAuthKeygen(key);
return Key.fromBytes(key);
}
@Override
public String cryptoAuth(String message, Key key) throws SodiumException {
byte[] tag = randomBytesBuf(Auth.BYTES);
byte[] messageBytes = bytes(message);
byte[] keyBytes = key.getAsBytes();
boolean res = cryptoAuth(tag, messageBytes, messageBytes.length, keyBytes);
if (!res) {
throw new SodiumException("Could not apply auth tag to your message.");
}
return messageEncoder.encode(tag);
}
@Override
public boolean cryptoAuthVerify(String tag, String message, Key key) {
byte[] tagToBytes = messageEncoder.decode(tag);
byte[] messageBytes = bytes(message);
byte[] keyBytes = key.getAsBytes();
return cryptoAuthVerify(tagToBytes, messageBytes, messageBytes.length, keyBytes);
}
@Override
public void cryptoAuthHMACSha256Keygen(byte[] key) {
getSodium().crypto_auth_hmacsha256_keygen(key);
}
@Override
public boolean cryptoAuthHMACSha256(byte[] out, byte[] in, long inLen, byte[] k) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth_hmacsha256(out, in, inLen, k));
}
@Override
public boolean cryptoAuthHMACSha256Verify(byte[] h, byte[] in, long inLen, byte[] k) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth_hmacsha256_verify(h, in, inLen, k));
}
@Override
public boolean cryptoAuthHMACSha256Init(Auth.StateHMAC256 state, byte[] key, int keyLen) {
if (keyLen < 0 || keyLen > key.length) {
throw new IllegalArgumentException("keyLen out of bounds: " + keyLen);
}
return successful(getSodium().crypto_auth_hmacsha256_init(state, key, keyLen));
}
@Override
public boolean cryptoAuthHMACSha256Update(Auth.StateHMAC256 state, byte[] in, long inLen) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth_hmacsha256_update(state, in, inLen));
}
@Override
public boolean cryptoAuthHMACSha256Final(Auth.StateHMAC256 state, byte[] out) {
return successful(getSodium().crypto_auth_hmacsha256_final(state, out));
}
@Override
public void cryptoAuthHMACSha512Keygen(byte[] key) {
getSodium().crypto_auth_hmacsha512_keygen(key);
}
@Override
public boolean cryptoAuthHMACSha512(byte[] out, byte[] in, long inLen, byte[] k) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth_hmacsha512(out, in, inLen, k));
}
@Override
public boolean cryptoAuthHMACSha512Verify(byte[] h, byte[] in, long inLen, byte[] k) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth_hmacsha512_verify(h, in, inLen, k));
}
@Override
public boolean cryptoAuthHMACSha512Init(Auth.StateHMAC512 state, byte[] key, int keyLen) {
if (keyLen < 0 || keyLen > key.length) {
throw new IllegalArgumentException("keyLen out of bounds: " + keyLen);
}
return successful(getSodium().crypto_auth_hmacsha512_init(state, key, keyLen));
}
@Override
public boolean cryptoAuthHMACSha512Update(Auth.StateHMAC512 state, byte[] in, long inLen) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth_hmacsha512_update(state, in, inLen));
}
@Override
public boolean cryptoAuthHMACSha512Final(Auth.StateHMAC512 state, byte[] out) {
return successful(getSodium().crypto_auth_hmacsha512_final(state, out));
}
@Override
public void cryptoAuthHMACSha512256Keygen(byte[] key) {
getSodium().crypto_auth_hmacsha512256_keygen(key);
}
@Override
public boolean cryptoAuthHMACSha512256(byte[] out, byte[] in, long inLen, byte[] k) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth_hmacsha512256(out, in, inLen, k));
}
@Override
public boolean cryptoAuthHMACSha512256Verify(byte[] h, byte[] in, long inLen, byte[] k) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth_hmacsha512256_verify(h, in, inLen, k));
}
@Override
public boolean cryptoAuthHMACSha512256Init(Auth.StateHMAC512256 state, byte[] key, int keyLen) {
if (keyLen < 0 || keyLen > key.length) {
throw new IllegalArgumentException("keyLen out of bounds: " + keyLen);
}
return successful(getSodium().crypto_auth_hmacsha512256_init(state, key, keyLen));
}
@Override
public boolean cryptoAuthHMACSha512256Update(Auth.StateHMAC512256 state, byte[] in, long inLen) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_auth_hmacsha512256_update(state, in, inLen));
}
@Override
public boolean cryptoAuthHMACSha512256Final(Auth.StateHMAC512256 state, byte[] out) {
return successful(getSodium().crypto_auth_hmacsha512256_final(state, out));
}
@Override
public Key cryptoAuthHMACShaKeygen(Auth.Type type) {
if (type.equals(Auth.Type.SHA256)) {
byte[] k = new byte[Auth.HMACSHA256_KEYBYTES];
cryptoAuthHMACSha256Keygen(k);
return Key.fromBytes(k);
} else if (type.equals(Auth.Type.SHA512)) {
byte[] k = new byte[Auth.HMACSHA512_KEYBYTES];
cryptoAuthHMACSha512Keygen(k);
return Key.fromBytes(k);
} else {
byte[] k = new byte[Auth.HMACSHA512256_KEYBYTES];
cryptoAuthHMACSha512256Keygen(k);
return Key.fromBytes(k);
}
}
@Override
public String cryptoAuthHMACSha(Auth.Type type, String in, Key key) {
byte[] inBytes = bytes(in);
byte[] keyBytes = key.getAsBytes();
long inByteLen = inBytes.length;
if (type.equals(Auth.Type.SHA256)) {
byte[] out = new byte[Auth.HMACSHA256_BYTES];
cryptoAuthHMACSha256(out, inBytes, inByteLen, keyBytes);
return messageEncoder.encode(out);
} else if (type.equals(Auth.Type.SHA512)) {
byte[] out = new byte[Auth.HMACSHA512_BYTES];
cryptoAuthHMACSha512(out, inBytes, inByteLen, keyBytes);
return messageEncoder.encode(out);
} else {
byte[] out = new byte[Auth.HMACSHA512256_BYTES];
cryptoAuthHMACSha512256(out, inBytes, inByteLen, keyBytes);
return messageEncoder.encode(out);
}
}
@Override
public boolean cryptoAuthHMACShaVerify(Auth.Type type, String h, String in, Key key) {
byte[] authBytes = messageEncoder.decode(h);
byte[] inBytes = bytes(in);
byte[] keyBytes = key.getAsBytes();
long inByteLen = inBytes.length;
if (type.equals(Auth.Type.SHA256)) {
return cryptoAuthHMACSha256Verify(authBytes, inBytes, inByteLen, keyBytes);
} else if (type.equals(Auth.Type.SHA512)) {
return cryptoAuthHMACSha512Verify(authBytes, inBytes, inByteLen, keyBytes);
} else {
return cryptoAuthHMACSha512256Verify(authBytes, inBytes, inByteLen, keyBytes);
}
}
@Override
public boolean cryptoAuthHMACShaInit(Auth.StateHMAC256 state, Key key) {
byte[] keyBytes = key.getAsBytes();
return cryptoAuthHMACSha256Init(state, keyBytes, keyBytes.length);
}
@Override
public boolean cryptoAuthHMACShaUpdate(Auth.StateHMAC256 state, String in) {
byte[] inBytes = bytes(in);
long inByteLen = inBytes.length;
return cryptoAuthHMACSha256Update(state, inBytes, inByteLen);
}
@Override
public String cryptoAuthHMACShaFinal(Auth.StateHMAC256 state) throws SodiumException {
byte[] out = new byte[Auth.HMACSHA256_BYTES];
boolean res = cryptoAuthHMACSha256Final(state, out);
if (!res) {
throw new SodiumException("Could not finalise SHA Hash.");
}
return messageEncoder.encode(out);
}
@Override
public boolean cryptoAuthHMACShaInit(Auth.StateHMAC512 state, Key key) {
byte[] keyBytes = key.getAsBytes();
return cryptoAuthHMACSha512Init(state, keyBytes, keyBytes.length);
}
@Override
public boolean cryptoAuthHMACShaUpdate(Auth.StateHMAC512 state, String in) {
byte[] inBytes = bytes(in);
long inByteLen = inBytes.length;
return cryptoAuthHMACSha512Update(state, inBytes, inByteLen);
}
@Override
public String cryptoAuthHMACShaFinal(Auth.StateHMAC512 state) throws SodiumException {
byte[] out = new byte[Auth.HMACSHA512_BYTES];
boolean res = cryptoAuthHMACSha512Final(state, out);
if (!res) {
throw new SodiumException("Could not finalise HMAC Sha 512.");
}
return messageEncoder.encode(out);
}
@Override
public boolean cryptoAuthHMACShaInit(Auth.StateHMAC512256 state, Key key) {
byte[] keyBytes = key.getAsBytes();
return cryptoAuthHMACSha512256Init(state, keyBytes, keyBytes.length);
}
@Override
public boolean cryptoAuthHMACShaUpdate(Auth.StateHMAC512256 state, String in) {
byte[] inBytes = bytes(in);
long inByteLen = inBytes.length;
return cryptoAuthHMACSha512256Update(state, inBytes, inByteLen);
}
@Override
public String cryptoAuthHMACShaFinal(Auth.StateHMAC512256 state) throws SodiumException {
byte[] out = new byte[Auth.HMACSHA512256_BYTES];
boolean res = cryptoAuthHMACSha512256Final(state, out);
if (!res) {
throw new SodiumException("Could not finalise HMAC Sha 512256.");
}
return messageEncoder.encode(out);
}
//// -------------------------------------------|
//// SHORT HASH
//// -------------------------------------------|
@Override
public boolean cryptoShortHash(byte[] out, byte[] in, long inLen, byte[] key) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_shorthash(out, in, inLen, key));
}
@Override
public void cryptoShortHashKeygen(byte[] k) {
getSodium().crypto_shorthash_keygen(k);
}
@Override
public String cryptoShortHash(String in, Key key) throws SodiumException {
byte[] inBytes = hexToBytes(in);
byte[] keyBytes = key.getAsBytes();
byte[] out = randomBytesBuf(ShortHash.BYTES);
if (getSodium().crypto_shorthash(out, inBytes, inBytes.length, keyBytes) != 0) {
throw new SodiumException("Failed short-input hashing.");
}
return sodiumBin2Hex(out);
}
@Override
public Key cryptoShortHashKeygen() {
byte[] key = randomBytesBuf(ShortHash.SIPHASH24_KEYBYTES);
getSodium().crypto_shorthash_keygen(key);
return Key.fromBytes(key);
}
//// -------------------------------------------|
//// GENERIC HASH
//// -------------------------------------------|
@Override
public boolean cryptoGenericHash(byte[] out, int outLen, byte[] in, long inLen, byte[] key, int keyLen) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
if (outLen < 0 || outLen > out.length) {
throw new IllegalArgumentException("outLen out of bounds: " + outLen);
}
return successful(getSodium().crypto_generichash(out, outLen, in, inLen, key, keyLen));
}
@Override
public boolean cryptoGenericHash(byte[] out, int outLen, byte[] in, long inLen) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
if (outLen < 0 || outLen > out.length) {
throw new IllegalArgumentException("outLen out of bounds: " + outLen);
}
return successful(getSodium().crypto_generichash(out, outLen, in, inLen, null, 0));
}
@Override
public boolean cryptoGenericHashInit(byte[] state, byte[] key, int keyLength, int outLen) {
return successful(getSodium().crypto_generichash_init(state, key, keyLength, outLen));
}
@Override
public boolean cryptoGenericHashInit(byte[] state, int outLen) {
return successful(getSodium().crypto_generichash_init(state, null, 0, outLen));
}
@Override
public boolean cryptoGenericHashUpdate(byte[] state, byte[] in, long inLen) {
if (inLen < 0 || inLen > in.length) {
throw new IllegalArgumentException("inLen out of bounds: " + inLen);
}
return successful(getSodium().crypto_generichash_update(state, in, inLen));
}
@Override
public boolean cryptoGenericHashFinal(byte[] state, byte[] out, int outLen) {
return successful(getSodium().crypto_generichash_final(state, out, outLen));
}
@Override
public int cryptoGenericHashStateBytes() {
return getSodium().crypto_generichash_statebytes();
}
@Override
public void cryptoGenericHashKeygen(byte[] k) {
getSodium().crypto_generichash_keygen(k);
}
// -- lazy
@Override
public Key cryptoGenericHashKeygen() {
byte[] key = randomBytesBuf(GenericHash.KEYBYTES);
cryptoGenericHashKeygen(key);
return Key.fromBytes(key);
}
@Override
public Key cryptoGenericHashKeygen(int size) throws SodiumException {
byte[] key = randomBytesBuf(size);
cryptoGenericHashKeygen(key);
return Key.fromBytes(key);
}
@Override
public String cryptoGenericHash(String in, Key key) throws SodiumException {
byte[] message = bytes(in);
byte[] keyBytes = key.getAsBytes();
byte[] hash = randomBytesBuf(GenericHash.BYTES);
boolean res = cryptoGenericHash(hash, hash.length, message, message.length, keyBytes, keyBytes.length);
if (!res) {
throw new SodiumException("Could not hash the message.");
}
return messageEncoder.encode(hash);
}
@Override
public String cryptoGenericHash(String in) throws SodiumException {
byte[] message = bytes(in);
byte[] hash = randomBytesBuf(GenericHash.BYTES);
boolean res = cryptoGenericHash(hash, hash.length, message, message.length, null, 0);
if (!res) {
throw new SodiumException("Could not hash the message.");
}
return messageEncoder.encode(hash);
}
@Override
public boolean cryptoGenericHashInit(byte[] state, Key key, int outLen) {
byte[] keyBytes = key.getAsBytes();
return getSodium().crypto_generichash_init(state, keyBytes, keyBytes.length, outLen) == 0;
}
@Override
public boolean cryptoGenericHashUpdate(byte[] state, String in) {
byte[] inBytes = bytes(in);
return getSodium().crypto_generichash_update(state, inBytes, inBytes.length) == 0;
}
@Override
public String cryptoGenericHashFinal(byte[] state, int outLen) throws SodiumException {
byte[] hash = new byte[outLen];
boolean res = getSodium().crypto_generichash_final(state, hash, hash.length) == 0;
if (!res) {
throw new SodiumException("Could not finalise the hashing process.");
}
return messageEncoder.encode(hash);
}
//// -------------------------------------------|
//// AEAD
//// -------------------------------------------|
@Override
public void cryptoAeadChaCha20Poly1305Keygen(byte[] key) {
getSodium().crypto_aead_chacha20poly1305_keygen(key);
}
@Override
public boolean cryptoAeadChaCha20Poly1305Encrypt(byte[] c, long[] cLen, byte[] m, long mLen, byte[] ad, long adLen, byte[] nSec, byte[] nPub, byte[] k) {
if (mLen < 0 || mLen > m.length) {
throw new IllegalArgumentException("mLen out of bounds: " + mLen);
}
if (adLen < 0 || adLen > ad.length) {
throw new IllegalArgumentException("adLen out of bounds: " + adLen);
}
return successful(getSodium().crypto_aead_chacha20poly1305_encrypt(c, cLen, m, mLen, ad, adLen, nSec, nPub, k));
}
@Override
public boolean cryptoAeadChaCha20Poly1305Decrypt(byte[] m, long[] mLen, byte[] nSec, byte[] c, long cLen, byte[] ad, long adLen, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_chacha20poly1305_decrypt(m, mLen, nSec, c, cLen, ad, adLen, nPub, k));
}
@Override
public boolean cryptoAeadChaCha20Poly1305EncryptDetached(byte[] c, byte[] mac, long[] macLenAddress, byte[] m, long mLen, byte[] ad, long adLen, byte[] nSec, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_chacha20poly1305_encrypt_detached(c, mac, macLenAddress, m, mLen, ad, adLen, nSec, nPub, k));
}
@Override
public boolean cryptoAeadChaCha20Poly1305DecryptDetached(byte[] m, byte[] nSec, byte[] c, long cLen, byte[] mac, byte[] ad, long adLen, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_chacha20poly1305_decrypt_detached(m, nSec, c, cLen, mac, ad, adLen, nPub, k));
}
@Override
public void cryptoAeadChaCha20Poly1305IetfKeygen(byte[] key) {
getSodium().crypto_aead_chacha20poly1305_ietf_keygen(key);
}
@Override
public boolean cryptoAeadChaCha20Poly1305IetfEncrypt(byte[] c, long[] cLen, byte[] m, long mLen, byte[] ad, long adLen, byte[] nSec, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_chacha20poly1305_ietf_encrypt(c, cLen, m, mLen, ad, adLen, nSec, nPub, k));
}
@Override
public boolean cryptoAeadChaCha20Poly1305IetfDecrypt(byte[] m, long[] mLen, byte[] nSec, byte[] c, long cLen, byte[] ad, long adLen, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_chacha20poly1305_ietf_decrypt(m, mLen, nSec, c, cLen, ad, adLen, nPub, k));
}
@Override
public boolean cryptoAeadChaCha20Poly1305IetfEncryptDetached(byte[] c, byte[] mac, long[] macLenAddress, byte[] m, long mLen, byte[] ad, long adLen, byte[] nSec, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, macLenAddress, m, mLen, ad, adLen, nSec, nPub, k));
}
@Override
public boolean cryptoAeadChaCha20Poly1305IetfDecryptDetached(byte[] m, byte[] nSec, byte[] c, long cLen, byte[] mac, byte[] ad, long adLen, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_chacha20poly1305_ietf_decrypt_detached(m, nSec, c, cLen, mac, ad, adLen, nPub, k));
}
@Override
public void cryptoAeadXChaCha20Poly1305IetfKeygen(byte[] k) {
getSodium().crypto_aead_xchacha20poly1305_ietf_keygen(k);
}
@Override
public boolean cryptoAeadXChaCha20Poly1305IetfEncrypt(byte[] c, long[] cLen, byte[] m, long mLen, byte[] ad, long adLen, byte[] nSec, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_xchacha20poly1305_ietf_encrypt(c, cLen, m, mLen, ad, adLen, nSec, nPub, k));
}
@Override
public boolean cryptoAeadXChaCha20Poly1305IetfDecrypt(byte[] m, long[] mLen, byte[] nSec, byte[] c, long cLen, byte[] ad, long adLen, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_xchacha20poly1305_ietf_decrypt(m, mLen, nSec, c, cLen, ad, adLen, nPub, k));
}
@Override
public boolean cryptoAeadXChaCha20Poly1305IetfEncryptDetached(byte[] c, byte[] mac, long[] macLenAddress, byte[] m, long mLen, byte[] ad, long adLen, byte[] nSec, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_xchacha20poly1305_ietf_encrypt_detached(c, mac, macLenAddress, m, mLen, ad, adLen, nSec, nPub, k));
}
@Override
public boolean cryptoAeadXChaCha20Poly1305IetfDecryptDetached(byte[] m, byte[] nSec, byte[] c, long cLen, byte[] mac, byte[] ad, long adLen, byte[] nPub, byte[] k) {
return successful(getSodium().crypto_aead_xchacha20poly1305_ietf_decrypt_detached(m, nSec, c, cLen, mac, ad, adLen, nPub, k));
}
@Override
public void cryptoAeadAES256GCMKeygen(byte[] key) {
getSodium().crypto_aead_aes256gcm_keygen(key);
}
@Override
public boolean cryptoAeadAES256GCMEncrypt(byte[] cipher, long[] cipherLen, byte[] message, long messageLen, byte[] additionalData, long additionalDataLen, byte[] nSec, byte[] nPub, byte[] key) {
return successful(getSodium().crypto_aead_aes256gcm_encrypt(cipher, cipherLen, message, messageLen, additionalData, additionalDataLen, nSec, nPub, key));
}
@Override
public boolean cryptoAeadAES256GCMDecrypt(byte[] message, long[] messageLen, byte[] nSec, byte[] cipher, long cipherLen, byte[] additionalData, long additionalDataLen, byte[] nPub, byte[] key) {
return successful(getSodium().crypto_aead_aes256gcm_decrypt(message, messageLen, nSec, cipher, cipherLen, additionalData, additionalDataLen, nPub, key));
}
@Override
public boolean cryptoAeadAES256GCMEncryptDetached(byte[] cipher, byte[] mac, long[] macLenAddress, byte[] message, long messageLen, byte[] additionalData, long additionalDataLen, byte[] nSec, byte[] nPub, byte[] key) {
return successful(getSodium().crypto_aead_aes256gcm_encrypt_detached(cipher, mac, macLenAddress, message, messageLen, additionalData, additionalDataLen, nSec, nPub, key));
}
@Override
public boolean cryptoAeadAES256GCMDecryptDetached(byte[] message, byte[] nSec, byte[] cipher, long cipherLen, byte[] mac, byte[] additionalData, long additionalDataLen, byte[] nPub, byte[] key) {
return successful(getSodium().crypto_aead_aes256gcm_decrypt_detached(message, nSec, cipher, cipherLen, mac, additionalData, additionalDataLen, nPub, key));
}
@Override
public boolean cryptoAeadAES256GCMIsAvailable() {
return getSodium().crypto_aead_aes256gcm_is_available() == 1;
}
// -- lazy
@Override
public Key keygen(AEAD.Method method) {
switch (method) {
case CHACHA20_POLY1305:
byte[] key = randomBytesBuf(AEAD.CHACHA20POLY1305_KEYBYTES);
cryptoAeadChaCha20Poly1305Keygen(key);
return Key.fromBytes(key);
case CHACHA20_POLY1305_IETF:
byte[] key2 = randomBytesBuf(AEAD.CHACHA20POLY1305_IETF_KEYBYTES);
cryptoAeadChaCha20Poly1305IetfKeygen(key2);
return Key.fromBytes(key2);
case XCHACHA20_POLY1305_IETF:
byte[] key3 = randomBytesBuf(AEAD.XCHACHA20POLY1305_IETF_KEYBYTES);
cryptoAeadXChaCha20Poly1305IetfKeygen(key3);
return Key.fromBytes(key3);
case AES256GCM:
byte[] key4 = randomBytesBuf(AEAD.AES256GCM_KEYBYTES);
cryptoAeadAES256GCMKeygen(key4);
return Key.fromBytes(key4);
}
return null;
}
@Override
public String encrypt(String m, String additionalData, byte[] nPub, Key k, AEAD.Method method) {
return encrypt(m, additionalData, null, nPub, k, method);
}
@Override
public String encrypt(String m, String additionalData, byte[] nSec, byte[] nPub, Key k, AEAD.Method method) {
byte[] messageBytes = bytes(m);
byte[] additionalDataBytes = additionalData == null ? new byte[0] : bytes(additionalData);
long additionalBytesLen = additionalData == null ? 0L : additionalDataBytes.length;
byte[] keyBytes = k.getAsBytes();
if (method.equals(AEAD.Method.CHACHA20_POLY1305)) {
byte[] cipherBytes = new byte[messageBytes.length + AEAD.CHACHA20POLY1305_ABYTES];
cryptoAeadChaCha20Poly1305Encrypt(
cipherBytes,
null,
messageBytes,
messageBytes.length,
additionalDataBytes,
additionalBytesLen,
nSec,
nPub,
keyBytes
);
return messageEncoder.encode(cipherBytes);
} else if (method.equals(AEAD.Method.CHACHA20_POLY1305_IETF)) {
byte[] cipherBytes = new byte[messageBytes.length + AEAD.CHACHA20POLY1305_IETF_ABYTES];
cryptoAeadChaCha20Poly1305IetfEncrypt(
cipherBytes,
null,
messageBytes,
messageBytes.length,
additionalDataBytes,
additionalBytesLen,
nSec,
nPub,
keyBytes
);
return messageEncoder.encode(cipherBytes);
} else if (method.equals(AEAD.Method.XCHACHA20_POLY1305_IETF)) {
byte[] cipherBytes3 = new byte[messageBytes.length + AEAD.XCHACHA20POLY1305_IETF_ABYTES];
cryptoAeadXChaCha20Poly1305IetfEncrypt(
cipherBytes3,
null,
messageBytes,
messageBytes.length,
additionalDataBytes,
additionalBytesLen,
nSec,
nPub,
keyBytes
);
return messageEncoder.encode(cipherBytes3);
} else {
byte[] cipherBytes = new byte[messageBytes.length + AEAD.AES256GCM_ABYTES];
cryptoAeadAES256GCMEncrypt(
cipherBytes,
null,
messageBytes,
messageBytes.length,
additionalDataBytes,
additionalBytesLen,
nSec,
nPub,
keyBytes
);
return messageEncoder.encode(cipherBytes);
}
}
@Override
public String decrypt(String cipher, String additionalData, byte[] nPub, Key k, AEAD.Method method) throws AEADBadTagException {
return decrypt(cipher, additionalData, null, nPub, k, method);
}
@Override
public String decrypt(String cipher, String additionalData, byte[] nSec, byte[] nPub, Key k, AEAD.Method method) throws AEADBadTagException {
byte[] cipherBytes = messageEncoder.decode(cipher);
byte[] additionalDataBytes = additionalData == null ? new byte[0] : bytes(additionalData);
long additionalBytesLen = additionalData == null ? 0L : additionalDataBytes.length;
byte[] keyBytes = k.getAsBytes();
if (method.equals(AEAD.Method.CHACHA20_POLY1305)) {
byte[] messageBytes = new byte[cipherBytes.length - AEAD.CHACHA20POLY1305_ABYTES];
if (!cryptoAeadChaCha20Poly1305Decrypt(
messageBytes,
null,
nSec,
cipherBytes,
cipherBytes.length,
additionalDataBytes,
additionalBytesLen,
nPub,
keyBytes
)) {
throw new AEADBadTagException();
}
return str(messageBytes);
} else if (method.equals(AEAD.Method.CHACHA20_POLY1305_IETF)) {
byte[] messageBytes = new byte[cipherBytes.length - AEAD.CHACHA20POLY1305_IETF_ABYTES];
if (!cryptoAeadChaCha20Poly1305IetfDecrypt(
messageBytes,
null,
nSec,
cipherBytes,
cipherBytes.length,
additionalDataBytes,
additionalBytesLen,
nPub,
keyBytes
)) {
throw new AEADBadTagException();
}
return str(messageBytes);
} else if (method.equals(AEAD.Method.XCHACHA20_POLY1305_IETF)) {
byte[] messageBytes = new byte[cipherBytes.length - AEAD.XCHACHA20POLY1305_IETF_ABYTES];
if (!cryptoAeadXChaCha20Poly1305IetfDecrypt(
messageBytes,
null,
nSec,
cipherBytes,
cipherBytes.length,
additionalDataBytes,
additionalBytesLen,
nPub,
keyBytes
)) {
throw new AEADBadTagException();
}
return str(messageBytes);
} else {
byte[] messageBytes = new byte[cipherBytes.length - AEAD.AES256GCM_ABYTES];
if (!cryptoAeadAES256GCMDecrypt(
messageBytes,
null,
nSec,
cipherBytes,
cipherBytes.length,
additionalDataBytes,
additionalBytesLen,
nPub,
keyBytes
)) {
throw new AEADBadTagException();
}
return str(messageBytes);
}
}
@Override
public DetachedEncrypt encryptDetached(String m, String additionalData, byte[] nSec, byte[] nPub, Key k, AEAD.Method method) {
byte[] messageBytes = bytes(m);
byte[] additionalDataBytes = additionalData == null ? new byte[0] : bytes(additionalData);
long additionalBytesLen = additionalData == null ? 0L : additionalDataBytes.length;
byte[] keyBytes = k.getAsBytes();
byte[] cipherBytes = new byte[messageBytes.length];
if (method.equals(AEAD.Method.CHACHA20_POLY1305)) {
byte[] macBytes = new byte[AEAD.CHACHA20POLY1305_ABYTES];
cryptoAeadChaCha20Poly1305EncryptDetached(
cipherBytes,
macBytes,
null,
messageBytes,
messageBytes.length,
additionalDataBytes,
additionalBytesLen,
nSec,
nPub,
keyBytes
);
return new DetachedEncrypt(cipherBytes, macBytes);
} else if (method.equals(AEAD.Method.CHACHA20_POLY1305_IETF)) {
byte[] macBytes = new byte[AEAD.CHACHA20POLY1305_IETF_ABYTES];
cryptoAeadChaCha20Poly1305IetfEncryptDetached(
cipherBytes,
macBytes,
null,
messageBytes,
messageBytes.length,
additionalDataBytes,
additionalBytesLen,
nSec,
nPub,
keyBytes
);
return new DetachedEncrypt(cipherBytes, macBytes);
} else if (method.equals(AEAD.Method.XCHACHA20_POLY1305_IETF)) {
byte[] macBytes = new byte[AEAD.XCHACHA20POLY1305_IETF_ABYTES];
cryptoAeadXChaCha20Poly1305IetfEncryptDetached(
cipherBytes,
macBytes,
null,
messageBytes,
messageBytes.length,
additionalDataBytes,
additionalBytesLen,
nSec,
nPub,
keyBytes
);
return new DetachedEncrypt(cipherBytes, macBytes);
} else {
byte[] macBytes = new byte[AEAD.AES256GCM_ABYTES];
cryptoAeadAES256GCMEncryptDetached(
cipherBytes,
macBytes,
null,
messageBytes,
messageBytes.length,
additionalDataBytes,
additionalBytesLen,
nSec,
nPub,
keyBytes
);
return new DetachedEncrypt(cipherBytes, macBytes);
}
}
@Override
public DetachedDecrypt decryptDetached(DetachedEncrypt detachedEncrypt, String additionalData, byte[] nSec, byte[] nPub, Key k, AEAD.Method method) throws AEADBadTagException {
byte[] cipherBytes = detachedEncrypt.getCipher();
byte[] additionalDataBytes = additionalData == null ? new byte[0] : bytes(additionalData);
long additionalBytesLen = additionalData == null ? 0L : additionalDataBytes.length;
byte[] keyBytes = k.getAsBytes();
byte[] messageBytes = new byte[cipherBytes.length];
byte[] macBytes = detachedEncrypt.getMac();
if (method.equals(AEAD.Method.CHACHA20_POLY1305)) {
if (!cryptoAeadChaCha20Poly1305DecryptDetached(
messageBytes,
nSec,
cipherBytes,
cipherBytes.length,
macBytes,
additionalDataBytes,
additionalBytesLen,
nPub,
keyBytes
)) {
throw new AEADBadTagException();
}
return new DetachedDecrypt(messageBytes, macBytes, charset);
} else if (method.equals(AEAD.Method.CHACHA20_POLY1305_IETF)) {
if (!cryptoAeadChaCha20Poly1305IetfDecryptDetached(
messageBytes,
nSec,
cipherBytes,
cipherBytes.length,
macBytes,
additionalDataBytes,
additionalBytesLen,
nPub,
keyBytes
)) {
throw new AEADBadTagException();
}
return new DetachedDecrypt(messageBytes, macBytes, charset);
} else if (method.equals(AEAD.Method.XCHACHA20_POLY1305_IETF)) {
if (!cryptoAeadXChaCha20Poly1305IetfDecryptDetached(
messageBytes,
nSec,
cipherBytes,
cipherBytes.length,
macBytes,
additionalDataBytes,
additionalBytesLen,
nPub,
keyBytes
)) {
throw new AEADBadTagException();
}
return new DetachedDecrypt(messageBytes, macBytes, charset);
} else {
if (!cryptoAeadAES256GCMDecryptDetached(
messageBytes,
nSec,
cipherBytes,
cipherBytes.length,
macBytes,
additionalDataBytes,
additionalBytesLen,
nPub,
keyBytes
)) {
throw new AEADBadTagException();
}
return new DetachedDecrypt(messageBytes, macBytes, charset);
}
}
//// -------------------------------------------|
//// Ristretto255
//// -------------------------------------------|
@Override
public boolean cryptoCoreRistretto255IsValidPoint(byte[] point) {
return point.length == Ristretto255.RISTRETTO255_BYTES
&& getSodium().crypto_core_ristretto255_is_valid_point(point) == 1;
}
@Override
public void cryptoCoreRistretto255Random(byte[] point) {
Checker.ensurePointFits(point);
getSodium().crypto_core_ristretto255_random(point);
}
@Override
public boolean cryptoCoreRistretto255FromHash(byte[] point, byte[] hash) {
Checker.ensurePointFits(point);
Checker.checkHash(hash);
return successful(getSodium().crypto_core_ristretto255_from_hash(point, hash));
}
@Override
public boolean cryptoScalarmultRistretto255(byte[] result, byte[] n, byte[] point) {
Checker.ensurePointFits(result);
Checker.checkPoint(point);
Checker.checkScalar(n);
return successful(getSodium().crypto_scalarmult_ristretto255(result, n, point));
}
@Override
public boolean cryptoScalarmultRistretto255Base(byte[] result, byte[] n) {
Checker.ensurePointFits(result);
Checker.checkScalar(n);
return successful(getSodium().crypto_scalarmult_ristretto255_base(result, n));
}
@Override
public boolean cryptoCoreRistretto255Add(byte[] result, byte[] p, byte[] q) {
Checker.ensurePointFits(result);
Checker.checkPoint(p);
Checker.checkPoint(q);
return successful(getSodium().crypto_core_ristretto255_add(result, p, q));
}
@Override
public boolean cryptoCoreRistretto255Sub(byte[] result, byte[] p, byte[] q) {
Checker.ensurePointFits(result);
Checker.checkPoint(p);
Checker.checkPoint(q);
return successful(getSodium().crypto_core_ristretto255_sub(result, p, q));
}
@Override
public void cryptoCoreRistretto255ScalarRandom(byte[] scalar) {
Checker.ensureScalarFits(scalar);
getSodium().crypto_core_ristretto255_scalar_random(scalar);
}
@Override
public void cryptoCoreRistretto255ScalarReduce(byte[] result, byte[] scalar) {
Checker.ensureScalarFits(result);
Checker.checkNonReducedScalar(scalar);
getSodium().crypto_core_ristretto255_scalar_reduce(result, scalar);
}
@Override
public boolean cryptoCoreRistretto255ScalarInvert(byte[] result, byte[] scalar) {
Checker.ensureScalarFits(result);
Checker.checkScalar(scalar);
return successful(getSodium().crypto_core_ristretto255_scalar_invert(result, scalar));
}
@Override
public void cryptoCoreRistretto255ScalarNegate(byte[] result, byte[] scalar) {
Checker.ensureScalarFits(result);
Checker.checkScalar(scalar);
getSodium().crypto_core_ristretto255_scalar_negate(result, scalar);
}
@Override
public void cryptoCoreRistretto255ScalarComplement(byte[] result, byte[] scalar) {
Checker.ensureScalarFits(result);
Checker.checkScalar(scalar);
getSodium().crypto_core_ristretto255_scalar_complement(result, scalar);
}
@Override
public void cryptoCoreRistretto255ScalarAdd(byte[] result, byte[] x, byte[] y) {
Checker.ensureScalarFits(result);
Checker.checkScalar(x);
Checker.checkScalar(y);
getSodium().crypto_core_ristretto255_scalar_add(result, x, y);
}
@Override
public void cryptoCoreRistretto255ScalarSub(byte[] result, byte[] x, byte[] y) {
Checker.ensureScalarFits(result);
Checker.checkScalar(x);
Checker.checkScalar(y);
getSodium().crypto_core_ristretto255_scalar_sub(result, x, y);
}
@Override
public void cryptoCoreRistretto255ScalarMul(byte[] result, byte[] x, byte[] y) {
Checker.ensureScalarFits(result);
Checker.checkScalar(x);
Checker.checkScalar(y);
getSodium().crypto_core_ristretto255_scalar_mul(result, x, y);
}
// -- lazy
@Override
public boolean cryptoCoreRistretto255IsValidPoint(String point) {
if (point == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255IsValidPoint(messageEncoder.decode(point));
}
@Override
public RistrettoPoint cryptoCoreRistretto255Random() {
byte[] point = Ristretto255.pointBuffer();
cryptoCoreRistretto255Random(point);
return RistrettoPoint.fromBytes(this, point);
}
@Override
public RistrettoPoint cryptoCoreRistretto255FromHash(String hash) throws SodiumException {
if (hash == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255FromHash(messageEncoder.decode(hash));
}
@Override
public RistrettoPoint cryptoCoreRistretto255FromHash(byte[] hash) throws SodiumException {
byte[] point = Ristretto255.pointBuffer();
if (!cryptoCoreRistretto255FromHash(point, hash)) {
throw new SodiumException("Conversion from hash to Ristretto point failed");
}
return RistrettoPoint.fromBytes(this, point);
}
@Override
public RistrettoPoint cryptoScalarmultRistretto255(BigInteger n, RistrettoPoint point)
throws SodiumException {
if (n == null || point == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoScalarmultRistretto255(Ristretto255.scalarToBytes(n), point);
}
@Override
public RistrettoPoint cryptoScalarmultRistretto255(String nEnc, RistrettoPoint point)
throws SodiumException {
if (nEnc == null || point == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoScalarmultRistretto255(messageEncoder.decode(nEnc), point);
}
@Override
public RistrettoPoint cryptoScalarmultRistretto255(byte[] n, RistrettoPoint point)
throws SodiumException {
byte[] result = Ristretto255.pointBuffer();
if (!cryptoScalarmultRistretto255(result, n, point.toBytes())) {
throw new SodiumException(
"Scalar multiplication failed. The resulting point was the identity element.");
}
return RistrettoPoint.fromBytes(this, result);
}
@Override
public RistrettoPoint cryptoScalarmultRistretto255Base(BigInteger n) throws SodiumException {
if (n == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoScalarmultRistretto255Base(Ristretto255.scalarToBytes(n));
}
@Override
public RistrettoPoint cryptoScalarmultRistretto255Base(String nEnc)
throws SodiumException {
if (nEnc == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoScalarmultRistretto255Base(messageEncoder.decode(nEnc));
}
@Override
public RistrettoPoint cryptoScalarmultRistretto255Base(byte[] n) throws SodiumException {
byte[] result = Ristretto255.pointBuffer();
if (!cryptoScalarmultRistretto255Base(result, n)) {
throw new SodiumException(
"Scalar multiplication failed. n was 0.");
}
return RistrettoPoint.fromBytes(this, result);
}
@Override
public RistrettoPoint cryptoCoreRistretto255Add(RistrettoPoint p, RistrettoPoint q)
throws SodiumException {
if (p == null || q == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
byte[] result = Ristretto255.pointBuffer();
if (!cryptoCoreRistretto255Add(result, p.toBytes(), q.toBytes())) {
throw new SodiumException("Either p or q was not a valid point.");
}
return RistrettoPoint.fromBytes(this, result);
}
@Override
public RistrettoPoint cryptoCoreRistretto255Sub(RistrettoPoint p, RistrettoPoint q)
throws SodiumException {
if (p == null || q == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
byte[] result = Ristretto255.pointBuffer();
if (!cryptoCoreRistretto255Sub(result, p.toBytes(), q.toBytes())) {
throw new SodiumException("Either p or q was not a valid point.");
}
return RistrettoPoint.fromBytes(this, result);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarRandom() {
byte[] scalar = Ristretto255.scalarBuffer();
cryptoCoreRistretto255ScalarRandom(scalar);
return Ristretto255.bytesToScalar(scalar);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarReduce(BigInteger scalar) {
if (scalar == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarReduce(Ristretto255.scalarToBytes(scalar, false));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarReduce(String scalarEnc) {
if (scalarEnc == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarReduce(messageEncoder.decode(scalarEnc));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarReduce(byte[] scalar) {
byte[] result = Ristretto255.scalarBuffer();
cryptoCoreRistretto255ScalarReduce(result, scalar);
return Ristretto255.bytesToScalar(result);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarInvert(BigInteger scalar)
throws SodiumException {
if (scalar == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarInvert(Ristretto255.scalarToBytes(scalar));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarInvert(String scalarEnc)
throws SodiumException {
if (scalarEnc == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarInvert(messageEncoder.decode(scalarEnc));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarInvert(byte[] scalar) throws SodiumException {
byte[] result = Ristretto255.scalarBuffer();
if (!cryptoCoreRistretto255ScalarInvert(result, scalar)) {
throw new SodiumException("Scalar inversion failed. Did you pass 0?");
}
return Ristretto255.bytesToScalar(result);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarNegate(BigInteger scalar) {
if (scalar == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarNegate(Ristretto255.scalarToBytes(scalar));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarNegate(String scalarEnc) {
if (scalarEnc == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarNegate(messageEncoder.decode(scalarEnc));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarNegate(byte[] scalar) {
byte[] result = Ristretto255.scalarBuffer();
cryptoCoreRistretto255ScalarNegate(result, scalar);
return Ristretto255.bytesToScalar(result);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarComplement(BigInteger scalar) {
if (scalar == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarComplement(Ristretto255.scalarToBytes(scalar));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarComplement(String scalarEnc) {
if (scalarEnc == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarComplement(messageEncoder.decode(scalarEnc));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarComplement(byte[] scalar) {
byte[] result = Ristretto255.scalarBuffer();
cryptoCoreRistretto255ScalarComplement(result, scalar);
return Ristretto255.bytesToScalar(result);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarAdd(BigInteger x, BigInteger y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarAdd(
Ristretto255.scalarToBytes(x), Ristretto255.scalarToBytes(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarAdd(BigInteger x, String y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarAdd(Ristretto255.scalarToBytes(x), messageEncoder.decode(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarAdd(String x, BigInteger y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarAdd(messageEncoder.decode(x), Ristretto255.scalarToBytes(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarAdd(String x, String y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarAdd(messageEncoder.decode(x), messageEncoder.decode(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarAdd(String x, byte[] y) {
if (x == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarAdd(messageEncoder.decode(x), y);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarAdd(byte[] x, String y) {
if (y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarAdd(x, messageEncoder.decode(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarAdd(BigInteger x, byte[] y) {
if (x == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarAdd(Ristretto255.scalarToBytes(x), y);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarAdd(byte[] x, BigInteger y) {
if (y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarAdd(x, Ristretto255.scalarToBytes(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarAdd(byte[] x, byte[] y) {
byte[] result = Ristretto255.scalarBuffer();
cryptoCoreRistretto255ScalarAdd(result, x, y);
return Ristretto255.bytesToScalar(result);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarSub(BigInteger x, BigInteger y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarSub(
Ristretto255.scalarToBytes(x), Ristretto255.scalarToBytes(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarSub(BigInteger x, String y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarSub(Ristretto255.scalarToBytes(x), messageEncoder.decode(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarSub(String x, BigInteger y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarSub(messageEncoder.decode(x), Ristretto255.scalarToBytes(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarSub(String x, String y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarSub(messageEncoder.decode(x), messageEncoder.decode(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarSub(String x, byte[] y) {
if (x == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarSub(messageEncoder.decode(x), y);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarSub(byte[] x, String y) {
if (y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarSub(x, messageEncoder.decode(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarSub(BigInteger x, byte[] y) {
if (x == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarSub(Ristretto255.scalarToBytes(x), y);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarSub(byte[] x, BigInteger y) {
if (y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarSub(x, Ristretto255.scalarToBytes(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarSub(byte[] x, byte[] y) {
byte[] result = Ristretto255.scalarBuffer();
cryptoCoreRistretto255ScalarSub(result, x, y);
return Ristretto255.bytesToScalar(result);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarMul(BigInteger x, BigInteger y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarMul(
Ristretto255.scalarToBytes(x), Ristretto255.scalarToBytes(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarMul(BigInteger x, String y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarMul(Ristretto255.scalarToBytes(x), messageEncoder.decode(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarMul(String x, BigInteger y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarMul(messageEncoder.decode(x), Ristretto255.scalarToBytes(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarMul(String x, String y) {
if (x == null || y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarMul(messageEncoder.decode(x), messageEncoder.decode(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarMul(String x, byte[] y) {
if (x == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarMul(messageEncoder.decode(x), y);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarMul(byte[] x, String y) {
if (y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarMul(x, messageEncoder.decode(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarMul(BigInteger x, byte[] y) {
if (x == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarMul(Ristretto255.scalarToBytes(x), y);
}
@Override
public BigInteger cryptoCoreRistretto255ScalarMul(byte[] x, BigInteger y) {
if (y == null) {
throw new IllegalArgumentException("null arguments are invalid");
}
return cryptoCoreRistretto255ScalarMul(x, Ristretto255.scalarToBytes(y));
}
@Override
public BigInteger cryptoCoreRistretto255ScalarMul(byte[] x, byte[] y) {
byte[] result = Ristretto255.scalarBuffer();
cryptoCoreRistretto255ScalarMul(result, x, y);
return Ristretto255.bytesToScalar(result);
}
//// -------------------------------------------|
//// CONVENIENCE
//// -------------------------------------------|
@Override
public <T> T res(int res, T object) {
return (res != 0) ? null : object;
}
@Override
public boolean successful(int res) {
return (res == 0);
}
@Override
public String str(byte[] bs) {
return new String(bs, charset);
}
@Override
public String str(byte[] bs, Charset charset) {
if (charset == null) {
return new String(bs, this.charset);
}
return new String(bs, charset);
}
@Override
public byte[] bytes(String s) {
return s.getBytes(charset);
}
/**
* Encodes the given bytes, using this {@link LazySodium}'s associated
* {@link MessageEncoder}.
*
* @param bytes the bytes to encode
* @return the encoded string
*/
public String encodeToString(byte[] bytes) {
return messageEncoder.encode(bytes);
}
/**
* Decodes the given string to bytes, using this {@link LazySodium}'s associated
* {@link MessageEncoder}.
*
* @param encoded the encoded string
* @return the decoded bytes
*/
public byte[] decodeFromString(String encoded) {
return messageEncoder.decode(encoded);
}
@Override
public boolean wrongLen(byte[] bs, int shouldBe) {
return bs.length != shouldBe;
}
@Override
public boolean wrongLen(int byteLength, int shouldBe) {
return byteLength != shouldBe;
}
@Override
public boolean wrongLen(int byteLength, long shouldBe) {
return byteLength != shouldBe;
}
@Override
public byte[] removeNulls(byte[] bs) {
// First determine how many bytes to
// cut off the end by checking total of null bytes
int totalBytesToCut = 0;
for (int i = bs.length - 1; i >= 0; i--) {
byte b = bs[i];
if (b == 0) {
totalBytesToCut++;
}
}
// ... then we now can copy across the array
// without the null bytes.
int newLengthOfBs = bs.length - totalBytesToCut;
byte[] trimmed = new byte[newLengthOfBs];
System.arraycopy(bs, 0, trimmed, 0, newLengthOfBs);
return trimmed;
}
public abstract Sodium getSodium();
// --
//// -------------------------------------------|
//// MAIN
//// -------------------------------------------|
// --
public static void main(String[] args) throws SodiumException {
}
}
================================================
FILE: src/main/java/com/goterl/lazysodium/LazySodiumJava.java
================================================
/*
* Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.goterl.lazysodium;
import com.goterl.lazysodium.exceptions.SodiumException;
import com.goterl.lazysodium.interfaces.Scrypt;
import com.goterl.lazysodium.interfaces.StreamJava;
import com.goterl.lazysodium.utils.Key;
import com.goterl.lazysodium.interfaces.MessageEncoder;
import java.nio.charset.Charset;
public class LazySodiumJava extends LazySodium implements
Scrypt.Native, Scrypt.Lazy,
StreamJava.Native, StreamJava.Lazy {
private final SodiumJava sodium;
public LazySodiumJava(SodiumJava sodium) {
super();
this.sodium = sodium;
}
public LazySodiumJava(SodiumJava sodium, Charset charset) {
super(charset);
this.sodium = sodium;
}
public LazySodiumJava(SodiumJava sodium, MessageEncoder messageEncoder) {
super(messageEncoder);
this.sodium = sodium;
}
public LazySodiumJava(SodiumJava sodium, Charset charset, MessageEncoder messageEncoder) {
super(charset, messageEncoder);
this.sodium = sodium;
}
@Override
public boolean cryptoPwHashScryptSalsa208Sha256(byte[] out, long outLen, byte[] password, long passwordLen, byte[] salt, long opsLimit, long memLimit) {
return successful(getSodium().crypto_pwhash_scryptsalsa208sha256(out, outLen, password, passwordLen, salt, opsLimit, memLimit));
}
@Override
public boolean cryptoPwHashScryptSalsa208Sha256Str(byte[] out, byte[] password, long passwordLen, long opsLimit, long memLimit) {
return successful(getSodium().crypto_pwhash_scryptsalsa208sha256_str(out, password, passwordLen, opsLimit, memLimit));
}
@Override
public boolean cryptoPwHashScryptSalsa208Sha256StrVerify(byte[] str, byte[] password, long passwordLen) {
return successful(getSodium().crypto_pwhash_scryptsalsa208sha256_str_verify(str, password, passwordLen));
}
@Override
public boolean cryptoPwHashScryptSalsa208Sha256Ll(byte[] password, int passwordLen, byte[] salt, int saltLen, long N, long r, long p, byte[] buf, int bufLen) {
return successful(getSodium().crypto_pwhash_scryptsalsa208sha256_ll(password, passwordLen, salt, saltLen, N, r, p, buf, bufLen));
}
@Override
public boolean cryptoPwHashScryptSalsa208Sha256StrNeedsRehash(byte[] hash, long opsLimit, long memLimit) {
return successful(getSodium().crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(hash, opsLimit, memLimit));
}
// Lazy Scrypt
@Override
public String cryptoPwHashScryptSalsa208Sha256(String password, long hashLen, byte[] salt, long opsLimit, long memLimit) throws SodiumException {
byte[] passwordBytes = bytes(password);
Scrypt.Checker.checkAllScrypt(passwordBytes.length, salt.length, hashLen, opsLimit, memLimit);
byte[] hash = new byte[longToInt(hashLen)];
boolean res = cryptoPwHashScryptSalsa208Sha256(hash, hash.length, passwordBytes, passwordBytes.length, salt, opsLimit, memLimit);
if (!res) {
throw new SodiumException("Could not Scrypt hash your password.");
}
return messageEncoder.encode(hash);
}
@Override
public String cryptoPwHashScryptSalsa208Sha256Str(String password, long opsLimit, long memLimit) throws SodiumException {
byte[] passwordBytes = bytes(password);
if (!Scrypt.Checker.checkOpsLimitScrypt(opsLimit)) {
throw new SodiumException("The ops limit provided is not between the correct values.");
}
if (!Scrypt.Checker.checkMemLimitScrypt(memLimit)) {
throw new SodiumException("The mem limit provided is not between the correct values.");
}
byte[] hash = new byte[longToInt(Scrypt.SCRYPTSALSA208SHA256_STRBYTES)];
boolean res = cryptoPwHashScryptSalsa208Sha256Str(hash, passwordBytes, passwordBytes.length, opsLimit, memLimit);
if (!res) {
throw new SodiumException("Could not string Scrypt hash your password.");
}
return messageEncoder.encode(hash);
}
@Override
public boolean cryptoPwHashScryptSalsa208Sha256StrVerify(String hash, String password) {
byte[] hashBytes = messageEncoder.decode(hash);
byte[] passwordBytes = bytes(password);
// If the end of the hash does not have an null byte,
// let's add it.
byte endOfHash = hashBytes[hashBytes.length - 1];
if (endOfHash != 0) {
byte[] hashWithNullByte = new byte[hashBytes.length + 1];
System.arraycopy(hashBytes, 0, hashWithNullByte, 0, hashBytes.length);
hashBytes = hashWithNullByte;
}
return cryptoPwHashScryptSalsa208Sha256StrVerify(hashBytes, passwordBytes, passwordBytes.length);
}
// Salsa20 12 rounds
@Override
public void cryptoStreamSalsa2012Keygen(byte[] key) {
getSodium().crypto_stream_salsa2012_keygen(key);
}
@Override
public boolean cryptoStreamSalsa2012(byte[] c, long cLen, byte[] nonce, byte[] key) {
return successful(getSodium().crypto_stream_salsa2012(c, cLen, nonce, key));
}
@Override
public boolean cryptoStreamSalsa2012Xor(byte[] cipher, byte[] message, long messageLen, byte[] nonce, byte[] key) {
return successful(getSodium().crypto_stream_salsa2012_xor(cipher, message, messageLen, nonce, key));
}
// Salsa20 8 rounds
@Override
public void cryptoStreamSalsa208Keygen(byte[] key) {
getSodium().crypto_stream_salsa208_keygen(key);
}
@Override
public boolean cryptoStreamSalsa208(byte[] c, long cLen, byte[] nonce, byte[] key) {
return successful(getSodium().crypto_stream_salsa208(c, cLen, nonce, key));
}
@Override
public boolean cryptoStreamSalsa208Xor(byte[] cipher, byte[] message, long messageLen, byte[] nonce, byte[] key) {
return successful(getSodium().crypto_stream_salsa208_xor(cipher, message, messageLen, nonce, key));
}
@Override
public void cryptoStreamXChaCha20Keygen(byte[] key) {
getSodium().crypto_stream_xchacha20_keygen(key);
}
@Override
public boolean cryptoStreamXChaCha20(byte[] c, long cLen, byte[] nonce, byte[] key) {
return successful(getSodium().crypto_stream_xchacha20(c, cLen, nonce, key));
}
@Override
public boolean cryptoStreamXChaCha20Xor(byte[] cipher, byte[] message, long messageLen, byte[] nonce, byte[] key) {
return successful(getSodium().crypto_stream_xchacha20_xor(cipher, message, messageLen, nonce, key));
}
@Override
public boolean cryptoStreamXChaCha20Ic(byte[] cipher, byte[] message, long messageLen, byte[] nonce, long ic, byte[] key) {
return successful(getSodium().crypto_stream_xchacha20_xor_ic(cipher, message, messageLen, nonce, ic, key));
}
// lazy
@Override
public Key cryptoStreamKeygen(StreamJava.Method method) {
byte[] k;
if (method.equals(StreamJava.Method.SALSA20_8)) {
k = new byte[StreamJava.SALSA208_KEYBYTES];
getSodium().crypto_stream_salsa208_keygen(k);
} else if (method.equals(StreamJava.Method.SALSA20_12)) {
k = new byte[StreamJava.SALSA2012_KEYBYTES];
getSodium().crypto_stream_salsa2012_keygen(k);
} else {
k = new byte[StreamJava.XCHACHA20_KEYBYTES];
getSodium().crypto_stream_xchacha20_keygen(k);
}
return Key.fromBytes(k);
}
@Override
public byte[] cryptoStream(byte[] nonce, Key key, StreamJava.Method method) {
byte[] c = new byte[20];
int cLen = c.length;
if (method.equals(StreamJava.Method.SALSA20_8)) {
getSodium().crypto_stream_salsa208(c, cLen, nonce, key.getAsBytes());
} else if (method.equals(StreamJava.Method.SALSA20_12)) {
getSodium().crypto_stream_salsa2012(c, cLen, nonce, key.getAsBytes());
} else {
getSodium().crypto_stream_xchacha20(c, cLen, nonce, key.getAsBytes());
}
return c;
}
@Override
public String cryptoStreamXor(String message, byte[] nonce, Key key, StreamJava.Method method) {
byte[] mBytes = bytes(message);
return messageEncoder.encode(cryptoStreamDefaultXor(mBytes, nonce, key, method));
}
@Override
public String cryptoStreamXorDecrypt(String cipher, byte[] nonce, Key key, StreamJava.Method method) {
return str(cryptoStreamDefaultXor(messageEncoder.decode(cipher), nonce, key, method));
}
@Override
public String cryptoStreamXorIc(String message, byte[] nonce, long ic, Key key, StreamJava.Method method) {
byte[] mBytes = bytes(message);
return messageEncoder.encode(cryptoStreamDefaultXorIc(mBytes, nonce, ic, key, method));
}
@Override
public String cryptoStreamXorIcDecrypt(String cipher, byte[] nonce, long ic, Key key, StreamJava.Method method) {
return str(cryptoStreamDefaultXorIc(messageEncoder.decode(cipher), nonce, ic, key, method));
}
private byte[] cryptoStreamDefaultXor(byte[] messageBytes, byte[] nonce, Key key, StreamJava.Method method) {
int mLen = messageBytes.length;
byte[] cipher = new byte[mLen];
if (method.equals(StreamJava.Method.SALSA20_8)) {
cryptoStreamSalsa208Xor(cipher, messageBytes, mLen, nonce, key.getAsBytes());
} else if (method.equals(StreamJava.Method.SALSA20_12)) {
cryptoStreamSalsa2012Xor(cipher, messageBytes, mLen, nonce, key.getAsBytes());
} else {
cryptoStreamXChaCha20Xor(cipher, messageBytes, mLen, nonce, key.getAsBytes());
}
return cipher;
}
private byte[] cryptoStreamDefaultXorIc(byte[] messageBytes, byte[] nonce, long ic, Key key, StreamJava.Method method) {
int mLen = messageBytes.length;
byte[] cipher = new byte[mLen];
if (method.equals(StreamJava.Method.SALSA20_8)) {
cryptoStreamSalsa208Xor(cipher, messageBytes, mLen, nonce, key.getAsBytes());
} else if (method.equals(StreamJava.Method.SALSA20_12)) {
cryptoStreamSalsa2012Xor(cipher, messageBytes, mLen, nonce, key.getAsBytes());
} else {
cryptoStreamXChaCha20Ic(cipher, messageBytes, mLen, nonce, ic, key.getAsBytes());
}
return cipher;
}
public SodiumJava getSodium() {
return sodium;
}
}
================================================
FILE: src/main/java/com/goterl/lazysodium/Sodium.java
================================================
/*
* Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.goterl.lazysodium;
import com.goterl.lazysodium.interfaces.*;
import com.goterl.lazysodium.utils.Base64Facade;
import com.goterl.lazysodium.utils.Base64Java;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
public class Sodium {
public static Base64Facade base64Facade = new Base64Java();
protected Sodium() {
}
protected void onRegistered() {
if (sodium_init() == -1) {
throw new IllegalStateException("Sodium library could not be initialised p
gitextract_988v69l7/
├── .github/
│ └── workflows/
│ └── primary.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── azure-pipelines.yml
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── sample-app/
│ ├── build.gradle
│ ├── libs/
│ │ └── jansi.jar
│ └── src/
│ └── main/
│ └── kotlin/
│ └── Main.kt
├── settings.gradle
└── src/
├── main/
│ └── java/
│ └── com/
│ └── goterl/
│ └── lazysodium/
│ ├── LazySodium.java
│ ├── LazySodiumJava.java
│ ├── Sodium.java
│ ├── SodiumJava.java
│ ├── exceptions/
│ │ └── SodiumException.java
│ ├── interfaces/
│ │ ├── AEAD.java
│ │ ├── Auth.java
│ │ ├── Base.java
│ │ ├── Box.java
│ │ ├── DiffieHellman.java
│ │ ├── GenericHash.java
│ │ ├── Hash.java
│ │ ├── Helpers.java
│ │ ├── KeyDerivation.java
│ │ ├── KeyExchange.java
│ │ ├── MessageEncoder.java
│ │ ├── Padding.java
│ │ ├── PwHash.java
│ │ ├── Random.java
│ │ ├── Ristretto255.java
│ │ ├── Scrypt.java
│ │ ├── SecretBox.java
│ │ ├── SecretStream.java
│ │ ├── SecureMemory.java
│ │ ├── ShortHash.java
│ │ ├── Sign.java
│ │ ├── Stream.java
│ │ └── StreamJava.java
│ └── utils/
│ ├── Base64Facade.java
│ ├── Base64Java.java
│ ├── Base64MessageEncoder.java
│ ├── BaseChecker.java
│ ├── Constants.java
│ ├── Detached.java
│ ├── DetachedDecrypt.java
│ ├── DetachedEncrypt.java
│ ├── HexMessageEncoder.java
│ ├── Key.java
│ ├── KeyPair.java
│ ├── LibraryLoader.java
│ ├── LibraryLoadingException.java
│ └── SessionPair.java
└── test/
└── java/
└── com/
└── goterl/
└── lazysodium/
├── AEADTest.java
├── AuthTest.java
├── BaseTest.java
├── BoxTest.java
├── DiffieHellmanTest.java
├── GenericHashTest.java
├── HashTest.java
├── HelperTest.java
├── KeyDerivationTest.java
├── KeyExchangeTest.java
├── PaddingTest.java
├── PwHashTest.java
├── Ristretto255Test.java
├── SecretBoxTest.java
├── SecretStreamTest.java
├── SecureMemoryTest.java
├── ShortHashTest.java
├── SignTest.java
├── SodiumJavaTest.java
├── StreamTest.java
└── utils/
├── Base64MessageEncoderTest.java
├── HexMessageEncoderTest.java
└── SodiumConversionsTest.java
Condensed preview — 79 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (522K chars).
[
{
"path": ".github/workflows/primary.yml",
"chars": 2157,
"preview": "name: Checks\n\non:\n push:\n branches:\n - master\n pull_request:\n branches:\n - master\n\njobs:\n test:\n n..."
},
{
"path": ".gitignore",
"chars": 797,
"preview": "# Compiled source #\n###################\n*.com\n*.class\n*.exe\n*.o\n\n# Packages #\n############\n# it's better to unpack these..."
},
{
"path": "CHANGELOG.md",
"chars": 87,
"preview": "Please see the releases page on github https://github.com/terl/lazysodium-java/releases"
},
{
"path": "LICENSE.md",
"chars": 16724,
"preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\"..."
},
{
"path": "README.md",
"chars": 2257,
"preview": "<p align=\"center\"><img width=\"260\" src=\"https://filedn.com/lssh2fV92SE8dRT5CWJvvSy/lazysodium_large_transparent.png\" /><..."
},
{
"path": "azure-pipelines.yml",
"chars": 878,
"preview": "# DEPRECATED.\n# Azure Pipelines has been deprecated in favour of\n# GitHub Actions. See the .github/workflows folder\n\n# B..."
},
{
"path": "build.gradle",
"chars": 7264,
"preview": "\n/*\n * Copyright (c) Terl Tech Ltd • 14/06/19 17:54 • goterl.com\n *\n * This Source Code Form is subject to the terms of..."
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 494,
"preview": "#\n# Copyright (c) Terl Tech Ltd • 14/06/19 17:54 • goterl.com\n#\n# This Source Code Form is subject to the terms of the M..."
},
{
"path": "gradle.properties",
"chars": 265,
"preview": "#\n# Copyright (c) Terl Tech Ltd • 14/06/19 17:54 • goterl.com\n#\n# This Source Code Form is subject to the terms of the M..."
},
{
"path": "gradlew",
"chars": 5296,
"preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n## Gradle start up..."
},
{
"path": "gradlew.bat",
"chars": 2260,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r..."
},
{
"path": "sample-app/build.gradle",
"chars": 764,
"preview": "plugins {\n id 'org.jetbrains.kotlin.jvm' version '2.2.0-RC'\n id 'java'\n id 'application'\n}\n\ngroup 'com.goterl'..."
},
{
"path": "sample-app/src/main/kotlin/Main.kt",
"chars": 16032,
"preview": "import com.goterl.lazysodium.LazySodium\nimport com.goterl.lazysodium.LazySodiumJava\nimport com.goterl.lazysodium.SodiumJ..."
},
{
"path": "settings.gradle",
"chars": 549,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 14/06/19 17:54 • goterl.com\n *\n * This Source Code Form is subject to the terms of t..."
},
{
"path": "src/main/java/com/goterl/lazysodium/LazySodium.java",
"chars": 126225,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/LazySodiumJava.java",
"chars": 10682,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/Sodium.java",
"chars": 30722,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/SodiumJava.java",
"chars": 4275,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/exceptions/SodiumException.java",
"chars": 621,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/AEAD.java",
"chars": 9400,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Auth.java",
"chars": 7434,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Base.java",
"chars": 2165,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Box.java",
"chars": 10785,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/DiffieHellman.java",
"chars": 1391,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/GenericHash.java",
"chars": 7633,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Hash.java",
"chars": 2786,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Helpers.java",
"chars": 1113,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/KeyDerivation.java",
"chars": 3278,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/KeyExchange.java",
"chars": 7059,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/MessageEncoder.java",
"chars": 426,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Padding.java",
"chars": 1858,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/PwHash.java",
"chars": 11946,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Random.java",
"chars": 1640,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Ristretto255.java",
"chars": 40832,
"preview": "package com.goterl.lazysodium.interfaces;\n\nimport com.goterl.lazysodium.LazySodium;\nimport com.goterl.lazysodium.excepti..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Scrypt.java",
"chars": 7040,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/SecretBox.java",
"chars": 7244,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/SecretStream.java",
"chars": 9244,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/SecureMemory.java",
"chars": 3841,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/ShortHash.java",
"chars": 1975,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Sign.java",
"chars": 11233,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/Stream.java",
"chars": 4661,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/interfaces/StreamJava.java",
"chars": 3465,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/Base64Facade.java",
"chars": 419,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/Base64Java.java",
"chars": 635,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/Base64MessageEncoder.java",
"chars": 733,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/BaseChecker.java",
"chars": 787,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/Constants.java",
"chars": 661,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/Detached.java",
"chars": 606,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/DetachedDecrypt.java",
"chars": 1043,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/DetachedEncrypt.java",
"chars": 694,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/HexMessageEncoder.java",
"chars": 688,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/Key.java",
"chars": 3740,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/KeyPair.java",
"chars": 929,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/LibraryLoader.java",
"chars": 6763,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/LibraryLoadingException.java",
"chars": 632,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/main/java/com/goterl/lazysodium/utils/SessionPair.java",
"chars": 927,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/AEADTest.java",
"chars": 11222,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/AuthTest.java",
"chars": 4978,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/BaseTest.java",
"chars": 713,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/BoxTest.java",
"chars": 5192,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/DiffieHellmanTest.java",
"chars": 2088,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/GenericHashTest.java",
"chars": 2606,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/HashTest.java",
"chars": 2334,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/HelperTest.java",
"chars": 685,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/KeyDerivationTest.java",
"chars": 6136,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/KeyExchangeTest.java",
"chars": 2357,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/PaddingTest.java",
"chars": 2963,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/PwHashTest.java",
"chars": 2705,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/Ristretto255Test.java",
"chars": 26599,
"preview": "package com.goterl.lazysodium;\n\n\nimport com.goterl.lazysodium.exceptions.SodiumException;\nimport com.goterl.lazysodium.i..."
},
{
"path": "src/test/java/com/goterl/lazysodium/SecretBoxTest.java",
"chars": 1344,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/SecretStreamTest.java",
"chars": 2079,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/SecureMemoryTest.java",
"chars": 1671,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/ShortHashTest.java",
"chars": 822,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/SignTest.java",
"chars": 6278,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/SodiumJavaTest.java",
"chars": 1049,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/StreamTest.java",
"chars": 4997,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/utils/Base64MessageEncoderTest.java",
"chars": 1069,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/utils/HexMessageEncoderTest.java",
"chars": 807,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
},
{
"path": "src/test/java/com/goterl/lazysodium/utils/SodiumConversionsTest.java",
"chars": 3351,
"preview": "/*\n * Copyright (c) Terl Tech Ltd • 01/04/2021, 12:31 • goterl.com\n *\n * This Source Code Form is subject to the terms o..."
}
]
About this extraction
This page contains the full source code of the terl/lazysodium-java GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 81 files (488.4 KB), approximately 119.3k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.