Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions devkit-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,10 @@ dependencies {
val logbackVersion: String by project
val junitVersion: String by project

compileOnly("org.slf4j:slf4j-api:$slf4jVersion")
implementation("ch.qos.logback:logback-classic:$logbackVersion")
compileOnly(libs.slf4j)
implementation(libs.logback)

testCompileOnly("org.slf4j:slf4j-api:$slf4jVersion")
testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion")
testImplementation(libs.junit)
}

tasks.test {
Expand Down
14 changes: 4 additions & 10 deletions devkit-utils/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,10 @@ tasks.withType<Jar> {
}

dependencies {
val slf4jVersion: String by project
val logbackVersion: String by project
val junitVersion: String by project

compileOnly("org.slf4j:slf4j-api:$slf4jVersion")
implementation("ch.qos.logback:logback-classic:$logbackVersion")
implementation(project(":devkit-core"))

testCompileOnly("org.slf4j:slf4j-api:$slf4jVersion")
testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion")
compileOnly(libs.slf4j)
implementation(libs.logback)
api(project(":devkit-core"))
testImplementation(libs.junit)
}

tasks.test {
Expand Down
10 changes: 1 addition & 9 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,4 @@ artefactVersion=2.1.0
projectUrl=https://onixbyte.com/JDevKit
projectGithubUrl=https://github.com/OnixByte/JDevKit
licenseName=The Apache License, Version 2.0
licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.txt

jacksonVersion=2.18.2
javaJwtVersion=4.4.0
junitVersion=5.11.4
logbackVersion=1.5.16
slf4jVersion=2.0.16
springVersion=6.2.2
springBootVersion=3.4.2
licenseUrl=https://www.apache.org/licenses/LICENSE-2.0.txt
36 changes: 36 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright (C) 2024-2025 OnixByte.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# See the License for the specific language governing permissions and
# limitations under the License.

[versions]
slf4j = "2.0.17"
logback = "1.5.18"
jackson = "2.18.3"
jwt = "4.5.0"
spring = "6.2.6"
springBoot = "3.4.4"
junit = "5.12.2"

[libraries]
slf4j = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" }
logback = { group = "ch.qos.logback", name = "logback-classic", version.ref = "logback" }
jackson-core = { group = "com.fasterxml.jackson.core", name = "jackson-core", version.ref = "jackson" }
jackson-databind = { group = "com.fasterxml.jackson.core", name = "jackson-databind", version.ref = "jackson" }
jwt = { group = "com.auth0", name = "java-jwt", version.ref = "jwt"}
spring-boot-autoconfigure = { group = "org.springframework.boot", name = "spring-boot-autoconfigure", version.ref = "springBoot" }
spring-boot-starter-logging = { group = "org.springframework.boot", name = "spring-boot-starter-logging", version.ref = "springBoot" }
spring-boot-configuration-processor = { group = "org.springframework.boot", name = "spring-boot-configuration-processor", version.ref = "springBoot" }
spring-boot-starter-redis = { group = "org.springframework.boot", name = "spring-boot-starter-data-redis", version.ref = "springBoot" }
spring-boot-starter-test = { group = "org.springframework.boot", name = "spring-boot-starter-test", version.ref = "springBoot" }
junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" }
14 changes: 4 additions & 10 deletions guid/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,10 @@ tasks.withType<Jar> {
}

dependencies {
val slf4jVersion: String by project
val logbackVersion: String by project
val junitVersion: String by project

compileOnly("org.slf4j:slf4j-api:$slf4jVersion")
implementation("ch.qos.logback:logback-classic:$logbackVersion")
implementation(project(":devkit-core"))

testCompileOnly("org.slf4j:slf4j-api:$slf4jVersion")
testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion")
compileOnly(libs.slf4j)
implementation(libs.logback)
api(project(":devkit-core"))
testImplementation(libs.junit)
}

tasks.test {
Expand Down
67 changes: 58 additions & 9 deletions key-pair-loader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,71 @@ ZyYNcH60ONRWjMqlQXozWMb2i7WphKxf8kopp42nzCflWQod+JQY+hM/EQ==
-----END PUBLIC KEY-----
```

#### Convert private key to EC formats which could be acceptable by Java
## RSA-based algorithm

Java's `PKCS8EncodedKeySpec` requires the private key to be in PKCS#8 format, while OpenSSL by
default generates private keys in traditional PEM format. To convert the private key, run the
following command:
### Generate key pair

#### Generate private key

Generate a private key by `genpkey` command provided by OpenSSL:

```shell
openssl pkcs8 -topk8 -inform PEM -outform PEM -in ec_private_key.pem -out ec_private_key_pkcs8.pem -nocrypt
openssl genpkey -algorithm RSA -out rsa_private_key.pem -pkeyopt rsa_keygen_bits:2048
```

The converted private key will look like this:
The output of this command is a file called `rsa_private_key.pem` and its content looks like the
following:

```text
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs79JlARgXEf6EDV7
+PHQCTHEMtqIoHOy1GZ1+ynQJ6yhRANCAARkA7GRY2i4gg8qx0XViAXUP9cPw9pn
Jg1wfrQ41FaMyqVBejNYxvaLtamErF/ySimnjafMJ+VZCh34lBj6Ez8R
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD4VIFYJFMAs15j
J3V3IicHd7sI2TIFqTZME40zlOlVAlPKLZmTQvZFLNgaUAAsvPi5i1DR2ywwK6Al
BfnwVnzvmDXC5mKHOz4oxOQVA6Nlp2yVaQMzidmfYNSkMtcv/4HRPsatc7K/M5l6
pCP20DVRjkikBdIy8e9w+x6BrIFp5Q8PZc/X2BGNAUMMYACdeYH5R/A0CxqkND13
esc4gkynMOrvZrZGHCz51usfSCqyDWWwsN+GG6LYWia4GkNlS0erQnP8gS93dfjl
e96BIfy3z7Iv+kUrf5ikNW2P8jMxLAv6LO+dcUAu9k477wIAF7Iq5KMuH/otsDOu
+h+2qXmBAgMBAAECggEAdRqcmC0g+y6arxV3fkObthjPGYAa57KBCWUa7B0n30+m
pavVRS2Jpttb2SSqwG4ouI6rARti/iBEd9EWqTCP4AieKZetFOpqCJ24lPRPRGus
d9S6jr5N4qut+vSCp37NABijZj4uJ540nTH0R7qtuhTnynl4Q0/1wwiYvTvVF1Lg
dn+I/8aRbshwDhdAOWOUe6GL7/eaCYgN8/UmlKIpp8tg0w2iWxbaFiR7gZiM41LA
M6SXXfcCas+ZVXsGbzQ3SNiVurCGuuRNcCScXS3/WoEDIb3cNtp49iOmQS+nmEoo
wh4uiEd+0+BrzxngS4o5+mKnHJnwgY0+veGVYLMR5QKBgQD9WKQmevMDU5c+NPq9
8jaR457Fuxq1gwzeFNJdWfOc/K2LEWh+nFNFCb++EboEj6FdxWaWNMxbrmJps5gs
EoBUYy/Tl7UycDqDfiYLmDdTsf2pVjjh9jaIADiLcJ8S6wwJMZKub7Tp8UVkenAl
535MqShLUC11Y7VxLb3Tsll4XwKBgQD67mm6iCmshr/eszPfNE3ylZ+PiNa7nat7
N7lQzBIiRJflT1kmVidC5gE+jASqH728ChkZZKxbHsjxpmWdAhLOITdXoTB4sDsd
wtV1lxkXxK9FnrpFvO3y1wZ/QsD3Z2KXxHYZqawkUETO9F3nqAXW0b2GDar5Qiyo
J3Tx/43aHwKBgDC0NMJtCoDONhowZy/S+6iqQKC0qprQec3L5PErVMkOTnKYwyTr
+pogGKt6ju9HiXcUdvdTaSIK8UJu00dNuzv94XjlBmGO78DNpJTAC4rcge5m9AKE
qdEVcclkukARzbuKuy8rrHT4/CUn4J141m/4aRWpcUPLCluato6XD9ozAoGBANvf
JhOFFgcPd3YazfvpZ9eE1XA+tfFlYYmxNRcgCU+vjO0oDvSxjutmgHae18N91pG6
w21lskSRf/+GDwl5dKLbphOJsOA/gz07qDDGOf2CoRW+1Hcg6drcINxH0K+4DkLv
qZApBSY4k2JH6zR+HMeztn6M4WBRZLHfCPC3PUN/AoGAA3AoHbLTZvqMIKSDkP4Y
U/tTsSFDY4aYo7LG/jk8af3oPU3KyGh4ZFBd6aMmXbS8f8FjvmrM+/e+y9OOGAlq
iOl0hYrs5cJSMLW6i4KnJYuYbMkgmk3bN2t9apu64xKR94gbPrI6AGnPZp+iIzp0
hXKe4HcuhQ3G0a2hjayiQ84=
-----END PRIVATE KEY-----
```

#### Generate public key by private key

Export public key from private key by OpenSSL:

```shell
openssl pkey -in rsa_private_key.pem -pubout -out rsa_public_key.pem
```

The output of this command is a file called `rsa_public_key.pem` and its content looks like the
following:

```text
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+FSBWCRTALNeYyd1dyIn
B3e7CNkyBak2TBONM5TpVQJTyi2Zk0L2RSzYGlAALLz4uYtQ0dssMCugJQX58FZ8
75g1wuZihzs+KMTkFQOjZadslWkDM4nZn2DUpDLXL/+B0T7GrXOyvzOZeqQj9tA1
UY5IpAXSMvHvcPsegayBaeUPD2XP19gRjQFDDGAAnXmB+UfwNAsapDQ9d3rHOIJM
pzDq72a2Rhws+dbrH0gqsg1lsLDfhhui2FomuBpDZUtHq0Jz/IEvd3X45XvegSH8
t8+yL/pFK3+YpDVtj/IzMSwL+izvnXFALvZOO+8CABeyKuSjLh/6LbAzrvoftql5
gQIDAQAB
-----END PUBLIC KEY-----
```
16 changes: 5 additions & 11 deletions key-pair-loader/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024-2024 OnixByte.
* Copyright (C) 2024-2025 OnixByte.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -52,16 +52,10 @@ tasks.withType<Jar> {
}

dependencies {
val slf4jVersion: String by project
val logbackVersion: String by project
val junitVersion: String by project

compileOnly("org.slf4j:slf4j-api:$slf4jVersion")
implementation("ch.qos.logback:logback-classic:$logbackVersion")
implementation(project(":devkit-core"))

testCompileOnly("org.slf4j:slf4j-api:$slf4jVersion")
testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion")
compileOnly(libs.slf4j)
implementation(libs.logback)
api(project(":devkit-core"))
testImplementation(libs.junit)
}

tasks.test {
Expand Down
25 changes: 25 additions & 0 deletions key-pair-loader/src/main/java/com/onixbyte/security/KeyLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,29 @@ public interface KeyLoader {
*/
PublicKey loadPublicKey(String pemKeyText);

/**
* Retrieves the raw content of a PEM formatted key by removing unnecessary headers, footers,
* and new line characters.
*
* <p>
* This method processes the provided PEM key text to return a cleaned string that contains
* only the key content. The method strips away the
* {@code "-----BEGIN (EC )?(PRIVATE|PUBLIC) KEY-----"} and
* {@code "-----END (EC )?(PRIVATE|PUBLIC) KEY-----"} lines, as well as any new line characters,
* resulting in a continuous string representation of the key, which can be used for further
* cryptographic operations.
*
* @param pemKeyText the PEM formatted key as a string, which may include headers, footers and
* line breaks
* @return a string containing the raw key content devoid of any unnecessary formatting
* or whitespace
*/
default String getRawContent(String pemKeyText) {
// remove all unnecessary parts of the pem key text
return pemKeyText
.replaceAll("-----BEGIN (EC )?(PRIVATE|PUBLIC) KEY-----", "")
.replaceAll("-----END (EC )?(PRIVATE|PUBLIC) KEY-----", "")
.replaceAll("\n", "");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,7 @@ public EcKeyLoader() {
@Override
public ECPrivateKey loadPrivateKey(String pemKeyText) {
try {
// remove all unnecessary parts of the pem key text
pemKeyText = pemKeyText
.replaceAll("-----BEGIN (EC )?PRIVATE KEY-----", "")
.replaceAll("-----END (EC )?PRIVATE KEY-----", "")
.replaceAll("\n", "");
pemKeyText = getRawContent(pemKeyText);
var decodedKeyString = decoder.decode(pemKeyText);
var keySpec = new PKCS8EncodedKeySpec(decodedKeyString);

Expand All @@ -112,11 +108,7 @@ public ECPrivateKey loadPrivateKey(String pemKeyText) {
@Override
public ECPublicKey loadPublicKey(String pemKeyText) {
try {
// remove all unnecessary parts of the pem key text
pemKeyText = pemKeyText
.replaceAll("-----BEGIN (EC )?PUBLIC KEY-----", "")
.replaceAll("-----END (EC )?PUBLIC KEY-----", "")
.replaceAll("\n", "");
pemKeyText = getRawContent(pemKeyText);
var keyBytes = decoder.decode(pemKeyText);
var spec = new X509EncodedKeySpec(keyBytes);
var key = keyFactory.generatePublic(spec);
Expand Down
Loading