Merge branch 'no-libsodium' into 'master'
No libsodium See merge request mangadex-pub/mangadex_at_home!65
This commit is contained in:
commit
602a43d62e
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -17,6 +17,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Security
|
||||
|
||||
## [1.2.2] - 2020-08-21
|
||||
### Changed
|
||||
- [2020-08-11] Moved to a Java implementation of NaCl [@carbotaniuman].
|
||||
|
||||
### Fixed
|
||||
- [2020-08-11] Revert WebUI changes in 1.2.1 [@carbotaniuman].
|
||||
|
||||
|
||||
## [1.2.1] - 2020-08-11
|
||||
### Added
|
||||
- [2020-08-11] New CLI for specifying database location, cache folder, and settings [@carbotaniuman].
|
||||
|
@ -234,7 +242,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Fixed
|
||||
- [2020-06-11] Tweaked logging configuration to reduce log file sizes by [@carbotaniuman].
|
||||
|
||||
[Unreleased]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/1.2.1...HEAD
|
||||
[Unreleased]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/1.2.2...HEAD
|
||||
[1.2.1]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/1.2.1...1.2.2
|
||||
[1.2.1]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/1.2.0...1.2.1
|
||||
[1.2.0]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/1.1.5...1.2.0
|
||||
[1.1.5]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/1.1.4...1.1.5
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
FROM openjdk:15-alpine
|
||||
WORKDIR /mangahome
|
||||
COPY /build/libs/mangadex_at_home.jar .
|
||||
RUN apk update && apk add --no-cache libsodium
|
||||
RUN apk update
|
||||
VOLUME "/mangahome/cache"
|
||||
EXPOSE 443 8080
|
||||
CMD java -Dfile-level=off -Dstdout-level=trace -jar mangadex_at_home.jar
|
|
@ -44,9 +44,6 @@ dependencies {
|
|||
|
||||
implementation group: "org.xerial", name: "sqlite-jdbc", version: "3.30.1"
|
||||
|
||||
implementation "com.goterl.lazycode:lazysodium-java:4.3.0"
|
||||
implementation "net.java.dev.jna:jna:5.5.0"
|
||||
|
||||
implementation "info.picocli:picocli:4.5.0"
|
||||
kapt "info.picocli:picocli-codegen:4.5.0"
|
||||
}
|
||||
|
|
3425
src/main/java/mdnet/security/TweetNaclFast.java
Normal file
3425
src/main/java/mdnet/security/TweetNaclFast.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -21,7 +21,7 @@ package mdnet.base
|
|||
import java.time.Duration
|
||||
|
||||
object Constants {
|
||||
const val CLIENT_BUILD = 18
|
||||
const val CLIENT_BUILD = 19
|
||||
|
||||
@JvmField val MAX_AGE_CACHE: Duration = Duration.ofDays(14)
|
||||
|
||||
|
|
|
@ -25,9 +25,6 @@ import com.fasterxml.jackson.databind.ObjectMapper
|
|||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.goterl.lazycode.lazysodium.LazySodiumJava
|
||||
import com.goterl.lazycode.lazysodium.SodiumJava
|
||||
import com.goterl.lazycode.lazysodium.exceptions.SodiumException
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
|
@ -54,6 +51,7 @@ import mdnet.base.trace
|
|||
import mdnet.base.warn
|
||||
import mdnet.cache.CachingInputStream
|
||||
import mdnet.cache.DiskLruCache
|
||||
import mdnet.security.TweetNaclFast
|
||||
import org.apache.http.client.config.CookieSpecs
|
||||
import org.apache.http.client.config.RequestConfig
|
||||
import org.apache.http.impl.client.HttpClients
|
||||
|
@ -91,6 +89,7 @@ class ImageServer(
|
|||
private val executor = Executors.newCachedThreadPool()
|
||||
|
||||
fun handler(dataSaver: Boolean, tokenized: Boolean = false): HttpHandler {
|
||||
val box = TweetNaclFast.SecretBox(remoteSettings.tokenKey)
|
||||
return baseHandler().then { request ->
|
||||
val chapterHash = Path.of("chapterHash")(request)
|
||||
val fileName = Path.of("fileName")(request)
|
||||
|
@ -114,19 +113,19 @@ class ImageServer(
|
|||
}
|
||||
val token = try {
|
||||
JACKSON.readValue<Token>(
|
||||
try {
|
||||
SODIUM.cryptoBoxOpenEasyAfterNm(
|
||||
tokenArr.sliceArray(24 until tokenArr.size), tokenArr.sliceArray(0 until 24), remoteSettings.tokenKey
|
||||
)
|
||||
} catch (_: SodiumException) {
|
||||
LOGGER.info { "Request for $sanitizedUri rejected for invalid token" }
|
||||
return@then Response(Status.FORBIDDEN)
|
||||
box.open(tokenArr.sliceArray(24 until tokenArr.size), tokenArr.sliceArray(0 until 24)).apply {
|
||||
if (this == null) {
|
||||
LOGGER.info { "Request for $sanitizedUri rejected for invalid token" }
|
||||
return@then Response(Status.FORBIDDEN)
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: JsonProcessingException) {
|
||||
LOGGER.info { "Request for $sanitizedUri rejected for invalid token" }
|
||||
println(e)
|
||||
LOGGER.info(e) { "Request for $sanitizedUri rejected for invalid token" }
|
||||
return@then Response(Status.FORBIDDEN)
|
||||
}
|
||||
println(token)
|
||||
|
||||
if (OffsetDateTime.now().isAfter(token.expires)) {
|
||||
LOGGER.info { "Request for $sanitizedUri rejected for expired token" }
|
||||
|
@ -164,6 +163,7 @@ class ImageServer(
|
|||
snapshot.close()
|
||||
LOGGER.warn { "Removing broken cache file for $sanitizedUri" }
|
||||
cache.removeUnsafe(imageId.toCacheId())
|
||||
cache.flush()
|
||||
}
|
||||
|
||||
request.handleCacheMiss(sanitizedUri, getRc4(rc4Bytes), imageId, imageDatum)
|
||||
|
@ -276,8 +276,11 @@ class ImageServer(
|
|||
if (editor.getLength(0) == contentLength.toLong()) {
|
||||
LOGGER.info { "Cache download for $sanitizedUri committed" }
|
||||
editor.commit()
|
||||
println("A")
|
||||
cache.flush()
|
||||
} else {
|
||||
LOGGER.warn { "Cache download for $sanitizedUri aborted" }
|
||||
println("B")
|
||||
editor.abort()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
@ -317,7 +320,6 @@ class ImageServer(
|
|||
.header("X-Cache", if (cached) "HIT" else "MISS")
|
||||
|
||||
companion object {
|
||||
private val SODIUM = LazySodiumJava(SodiumJava())
|
||||
private val JACKSON: ObjectMapper = jacksonObjectMapper()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.registerModule(JavaTimeModule())
|
||||
|
|
|
@ -19,31 +19,10 @@ along with this MangaDex@Home. If not, see <http://www.gnu.org/licenses/>.
|
|||
/* ktlint-disable no-wildcard-imports */
|
||||
package mdnet.base.server
|
||||
|
||||
import com.goterl.lazycode.lazysodium.LazySodiumJava
|
||||
import com.goterl.lazycode.lazysodium.exceptions.SodiumException
|
||||
import com.goterl.lazycode.lazysodium.interfaces.Box
|
||||
import java.security.MessageDigest
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
@Throws(SodiumException::class)
|
||||
fun LazySodiumJava.cryptoBoxOpenEasyAfterNm(cipherBytes: ByteArray, nonce: ByteArray, sharedKey: ByteArray): String {
|
||||
if (!Box.Checker.checkNonce(nonce.size)) {
|
||||
throw SodiumException("Incorrect nonce length.")
|
||||
}
|
||||
|
||||
if (!Box.Checker.checkBeforeNmBytes(sharedKey.size)) {
|
||||
throw SodiumException("Incorrect shared secret key length.")
|
||||
}
|
||||
|
||||
val message = ByteArray(cipherBytes.size - Box.MACBYTES)
|
||||
val res: Boolean = cryptoBoxOpenEasyAfterNm(message, cipherBytes, cipherBytes.size.toLong(), nonce, sharedKey)
|
||||
if (!res) {
|
||||
throw SodiumException("Could not fully complete shared secret key decryption.")
|
||||
}
|
||||
return str(message)
|
||||
}
|
||||
|
||||
fun getRc4(key: ByteArray): Cipher {
|
||||
val rc4 = Cipher.getInstance("RC4")
|
||||
rc4.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "RC4"))
|
Loading…
Reference in a new issue