Skip to content

Commit 881a017

Browse files
authored
1 parent 8587410 commit 881a017

File tree

13 files changed

+310
-211
lines changed

13 files changed

+310
-211
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@ build/
33
*.iml
44
.idea/
55
local.properties
6+
.kotlin/
7+
8+
gh-pages/*
9+
!gh-pages/publish.sh

README.md

+3-190
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ Low level core cryptographic components for Kotlin Multiplatform
2525
NOTE: For Jvm, `Digest` extends `java.security.MessageDigest` and `Mac` extends `javax.crypto.Mac`
2626
for interoperability.
2727

28-
Utilized by [KotlinCrypto/hash][url-hash] and [KotlinCrypto/MACs][url-macs]
29-
3028
### Library Authors
3129

3230
Modules in `core` are intentionally **single purpose** and **small** such that you
@@ -50,190 +48,9 @@ class FooFeatureA(digest: Digest) {
5048

5149
### Usage
5250

53-
<details>
54-
<summary>Digest</summary>
55-
56-
```kotlin
57-
// Using SHA256 from hash repo as an example
58-
import org.kotlincrypto.hash.sha2.SHA256
59-
60-
fun main() {
61-
val digest = SHA256()
62-
val bytes = Random.Default.nextBytes(615)
63-
64-
// Digest implements Algorithm
65-
println(digest.algorithm())
66-
67-
// Digest implements Updatable
68-
digest.update(5.toByte())
69-
digest.update(bytes)
70-
digest.update(bytes, 10, 88)
71-
72-
// Digest implements Resettable
73-
digest.reset()
74-
75-
digest.update(bytes)
76-
77-
// Digest implements Copyable
78-
val copy = digest.copy()
79-
80-
val hash = digest.digest()
81-
val hash2 = copy.digest(bytes)
82-
}
83-
```
84-
85-
</details>
86-
87-
<details>
88-
<summary>Mac</summary>
89-
90-
```kotlin
91-
// Using SecureRandom from the secure-random repo as an example
92-
import org.kotlincrypto.SecureRandom
93-
// Using HmacSHA3_256 from the MACs repo as an example
94-
import org.kotlincrypto.macs.hmac.sha3.HmacSHA3_256
95-
96-
fun main() {
97-
val key = SecureRandom().nextBytesOf(100)
98-
val mac = HmacSHA3_256(key)
99-
val bytes = Random.Default.nextBytes(615)
100-
101-
// Mac implements Algorithm
102-
println(mac.algorithm())
103-
104-
// Mac implements Updatable
105-
mac.update(5.toByte())
106-
mac.update(bytes)
107-
mac.update(bytes, 10, 88)
108-
109-
// Mac implements Resettable
110-
mac.reset()
111-
112-
mac.update(bytes)
113-
114-
// Mac implements Copyable
115-
val copy = mac.copy()
116-
117-
val hash = mac.doFinal()
118-
val hash2 = copy.doFinal(bytes)
119-
120-
// Reinitialize Mac instance with a new key
121-
// to use for something else.
122-
val newKey = SecureRandom().nextBytesOf(100)
123-
mac.reset(newKey = newKey)
124-
125-
// Zero out key material before dereferencing
126-
copy.clearKey()
127-
}
128-
```
129-
130-
</details>
131-
132-
<details>
133-
<summary>Xof</summary>
134-
135-
`XOF`s (i.e. [Extendable-Output Functions][url-pub-xof]) were introduced with `SHA3`.
136-
137-
`XOF`s are very similar to `Digest` and `Mac` except that instead of calling `digest()`
138-
or `doFinal()`, which returns a fixed size `ByteArray`, their output size can be variable
139-
in length.
140-
141-
As such, [KotlinCrypto][url-kotlin-crypto] takes the approach of making them distinctly
142-
different from those types, while implementing the same interfaces (`Algorithm`, `Copyable`,
143-
`Resettable`, `Updatable`).
144-
145-
Output for an `Xof` is done by reading, instead.
146-
147-
```kotlin
148-
// Using SHAKE128 from hash repo as an example
149-
import org.kotlincrypto.hash.sha3.SHAKE128
150-
151-
fun main() {
152-
val xof: Xof<SHAKE128> = SHAKE128.xOf()
153-
val bytes = Random.Default.nextBytes(615)
154-
155-
// Xof implements Algorithm
156-
println(xof.algorithm())
157-
158-
// Xof implements Updatable
159-
xof.update(5.toByte())
160-
xof.update(bytes)
161-
xof.update(bytes, 10, 88)
162-
163-
// Xof implements Resettable
164-
xof.reset()
165-
166-
xof.update(bytes)
167-
168-
// Xof implements Copyable
169-
xof.copy()
170-
171-
val out1 = ByteArray(100)
172-
val out2 = ByteArray(12345)
173-
174-
// Use produces a Reader which auto-closes when your action finishes.
175-
// Reader is using a snapshot of the Xof state (thus the
176-
// optional argument to resetXof with a default of true).
177-
xof.use(resetXof = false) { read(out1, 0, out1.size); read(out2) }
178-
179-
val out3 = ByteArray(out1.size)
180-
val out4 = ByteArray(out2.size)
181-
182-
// Can also create a Reader that won't auto-close
183-
val reader = xof.reader(resetXof = false)
184-
reader.read(out3)
185-
reader.read(out4)
186-
reader.close()
187-
188-
try {
189-
// The Reader has been closed and will throw
190-
// exception when trying to read from again.
191-
reader.use { read(out4) }
192-
} catch (e: IllegalStateException) {
193-
e.printStackTrace()
194-
}
195-
196-
// Contents are the same because Reader uses
197-
// a snapshot of Xof, which was not updated
198-
// between production of Readers.
199-
assertContentEquals(out1 + out2, out3 + out4)
200-
201-
// Still able to update Xof, independent of the production
202-
// and usage of Readers.
203-
xof.update(10.toByte())
204-
xof.use { read(out3); read(out4) }
205-
206-
try {
207-
assertContentEquals(out1 + out2, out3 + out4)
208-
throw IllegalStateException()
209-
} catch (_: AssertionError) {
210-
// pass
211-
}
212-
}
213-
```
214-
215-
```kotlin
216-
// Using KMAC128 from MACs repo as an example
217-
import org.kotlincrypto.macs.kmac.KMAC128
218-
// Using SecureRandom from the secure-random repo as an example
219-
import org.kotlincrypto.SecureRandom
220-
221-
fun main() {
222-
val key = SecureRandom().nextBytesOf(100)
223-
val kmacXof: Xof<KMAC128> = KMAC128.xOf(key)
224-
225-
// If Xof is for a Mac that implements ReKeyableXofAlgorithm,
226-
// reinitialize the instance via the `Xof.Companion.reset`
227-
// extension function for reuse.
228-
val newKey = SecureRandom().nextBytesOf(100)
229-
kmacXof.reset(newKey = newKey)
230-
231-
// Or zero out key material before dereferencing
232-
kmacXof.reset(newKey = ByteArray(1))
233-
}
234-
```
235-
236-
</details>
51+
- See module [digest](library/digest/README.md)
52+
- See module [mac](library/mac/README.md)
53+
- See module [xof](library/xof/README.md)
23754

23855
### Get Started
23956

@@ -280,8 +97,4 @@ dependencies {
28097
[url-latest-release]: https://github.com/KotlinCrypto/core/releases/latest
28198
[url-license]: https://www.apache.org/licenses/LICENSE-2.0.txt
28299
[url-kotlin]: https://kotlinlang.org
283-
[url-kotlin-crypto]: https://github.com/KotlinCrypto
284-
[url-hash]: https://github.com/KotlinCrypto/hash
285-
[url-macs]: https://github.com/KotlinCrypto/MACs
286100
[url-version-catalog]: https://github.com/KotlinCrypto/version-catalog
287-
[url-pub-xof]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf

build-logic/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ plugins {
1818
}
1919

2020
dependencies {
21+
implementation(libs.gradle.dokka)
2122
implementation(libs.gradle.kmp.configuration)
2223
implementation(libs.gradle.kotlin)
2324
implementation(libs.gradle.publish.maven)

build-logic/src/main/kotlin/-KmpConfigurationExtension.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ fun KmpConfigurationExtension.configureShared(
7171
mingwAll()
7272

7373
common {
74-
if (publish) pluginIds("publication")
74+
if (publish) pluginIds("publication", "dokka")
7575

7676
sourceSetTest {
7777
dependencies {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2025 Matthew Nelson
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
**/
16+
import org.jetbrains.dokka.DokkaConfiguration.Visibility
17+
import org.jetbrains.dokka.gradle.DokkaTaskPartial
18+
import java.net.URI
19+
20+
plugins {
21+
id("org.jetbrains.dokka")
22+
}
23+
24+
tasks.withType<DokkaTaskPartial>().configureEach {
25+
suppressInheritedMembers = true
26+
27+
dokkaSourceSets.configureEach {
28+
includes.from("README.md")
29+
noStdlibLink = true
30+
31+
sourceLink {
32+
localDirectory = rootDir
33+
remoteUrl = URI("https://github.com/KotlinCrypto/core/tree/master").toURL()
34+
remoteLineSuffix = "#L"
35+
}
36+
37+
documentedVisibilities.set(setOf(
38+
Visibility.PUBLIC,
39+
Visibility.PROTECTED,
40+
))
41+
}
42+
}

build.gradle.kts

+2-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ plugins {
2121
alias(libs.plugins.android.library) apply(false)
2222
alias(libs.plugins.benchmark) apply(false)
2323
alias(libs.plugins.binary.compat)
24+
alias(libs.plugins.dokka)
2425
alias(libs.plugins.kotlin.multiplatform) apply(false)
2526
}
2627

@@ -29,9 +30,7 @@ allprojects {
2930
findProperty("VERSION_NAME")?.let { version = it }
3031
findProperty("POM_DESCRIPTION")?.let { description = it.toString() }
3132

32-
repositories {
33-
mavenCentral()
34-
}
33+
repositories { mavenCentral() }
3534
}
3635

3736
@Suppress("PropertyName")

gh-pages/publish.sh

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright (c) 2025 Matthew Nelson
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
set -e
15+
16+
readonly DIR_SCRIPT="$( cd "$( dirname "$0" )" >/dev/null && pwd )"
17+
readonly REPO_NAME="core"
18+
19+
trap 'rm -rf "$DIR_SCRIPT/$REPO_NAME"' EXIT
20+
21+
cd "$DIR_SCRIPT"
22+
git clone -b gh-pages --single-branch https://github.com/KotlinCrypto/$REPO_NAME.git
23+
rm -rf "$DIR_SCRIPT/$REPO_NAME/"*
24+
echo "$REPO_NAME.kotlincrypto.org" > "$DIR_SCRIPT/$REPO_NAME/CNAME"
25+
26+
cd ..
27+
./gradlew clean -DKMP_TARGETS_ALL
28+
./gradlew dokkaHtmlMultiModule --no-build-cache -DKMP_TARGETS_ALL
29+
cp -aR build/dokka/htmlMultiModule/* gh-pages/$REPO_NAME
30+
31+
cd "$DIR_SCRIPT/$REPO_NAME"
32+
sed -i "s|module:|module:library/|g" "package-list"
33+
34+
git add --all
35+
git commit -S --message "Update dokka docs"
36+
git push

gradle/libs.versions.toml

+19-16
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
[versions]
2-
androidx-test-runner = "1.5.2"
2+
androidx-test-runner = "1.5.2"
33

4-
gradle-benchmark = "0.4.11"
5-
gradle-android = "8.2.2"
6-
gradle-binary-compat = "0.16.3"
7-
gradle-kmp-configuration = "0.3.2"
8-
gradle-kotlin = "1.9.24"
9-
gradle-publish-maven = "0.29.0"
4+
gradle-benchmark = "0.4.11"
5+
gradle-android = "8.2.2"
6+
gradle-binary-compat = "0.16.3"
7+
gradle-dokka = "1.9.20"
8+
gradle-kmp-configuration = "0.3.2"
9+
gradle-kotlin = "1.9.24"
10+
gradle-publish-maven = "0.29.0"
1011

1112
[libraries]
12-
gradle-kmp-configuration = { module = "io.matthewnelson:gradle-kmp-configuration-plugin", version.ref = "gradle-kmp-configuration" }
13-
gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "gradle-kotlin" }
14-
gradle-publish-maven = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "gradle-publish-maven" }
13+
gradle-dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "gradle-dokka" }
14+
gradle-kmp-configuration = { module = "io.matthewnelson:gradle-kmp-configuration-plugin", version.ref = "gradle-kmp-configuration" }
15+
gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "gradle-kotlin" }
16+
gradle-publish-maven = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "gradle-publish-maven" }
1517

1618
# tests & tools
17-
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test-runner" }
18-
benchmark-runtime = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime", version.ref = "gradle-benchmark" }
19+
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test-runner" }
20+
benchmark-runtime = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime", version.ref = "gradle-benchmark" }
1921

2022
[plugins]
21-
android-library = { id = "com.android.library", version.ref = "gradle-android" }
22-
benchmark = { id = "org.jetbrains.kotlinx.benchmark", version.ref = "gradle-benchmark" }
23-
binary-compat = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "gradle-binary-compat" }
24-
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "gradle-kotlin" }
23+
android-library = { id = "com.android.library", version.ref = "gradle-android" }
24+
benchmark = { id = "org.jetbrains.kotlinx.benchmark", version.ref = "gradle-benchmark" }
25+
binary-compat = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "gradle-binary-compat" }
26+
dokka = { id = "org.jetbrains.dokka", version.ref = "gradle-dokka" }
27+
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "gradle-kotlin" }

library/core/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Module core
2+
3+
Very small module, only containing public interfaces and exceptions. Is exported by all other modules.

0 commit comments

Comments
 (0)