squash
fix android module name import fixes fix some imports use `@atproto/jwk` over local zod schema preview oauth client rename package alignment more alignment database implementation cleanup some types alignment switch implementation for es256 half of `verifyJwt` for android half of `verifyJwt` for iOS rm log `createJwt` android `createJwt` ios rm print cleanup native impl silence some warnings reorg, finish web impl follow the `CryptoImplementation` move some more things around normalize some names rename func add generate on android add android dep rm bool add alg better implementation ios jwk generation fix index.ts add `getRandomValues()` on native web `getRandomValues` silence ts error for missing crypto on web add `digest` for web add `digest` add module
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
<manifest>
|
||||
</manifest>
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package expo.modules.blueskyoauthclient
|
||||
|
||||
import com.nimbusds.jose.Algorithm
|
||||
import java.security.KeyPairGenerator
|
||||
import java.security.MessageDigest
|
||||
import java.security.interfaces.ECPublicKey
|
||||
import java.security.interfaces.ECPrivateKey
|
||||
import com.nimbusds.jose.jwk.Curve
|
||||
import com.nimbusds.jose.jwk.ECKey
|
||||
import com.nimbusds.jose.jwk.KeyUse
|
||||
import java.util.UUID
|
||||
|
||||
class CryptoUtil {
|
||||
fun digest(data: ByteArray): ByteArray {
|
||||
val digest = MessageDigest.getInstance("sha256")
|
||||
return digest.digest(data)
|
||||
}
|
||||
|
||||
fun getRandomValues(byteLength: Int): ByteArray {
|
||||
val random = ByteArray(byteLength)
|
||||
java.security.SecureRandom().nextBytes(random)
|
||||
return random
|
||||
}
|
||||
|
||||
fun generateKeyPair(keyId: String?): Pair<String, String> {
|
||||
val keyIdString = keyId ?: UUID.randomUUID().toString()
|
||||
|
||||
val keyPairGen = KeyPairGenerator.getInstance("EC")
|
||||
keyPairGen.initialize(Curve.P_256.toECParameterSpec())
|
||||
val keyPair = keyPairGen.generateKeyPair()
|
||||
|
||||
val publicKey = keyPair.public as ECPublicKey
|
||||
val privateKey = keyPair.private as ECPrivateKey
|
||||
|
||||
val publicJwk = ECKey.Builder(Curve.P_256, publicKey)
|
||||
.keyUse(KeyUse.SIGNATURE)
|
||||
.algorithm(Algorithm.parse("ES256"))
|
||||
.keyID(keyIdString)
|
||||
.build()
|
||||
val privateJwk = ECKey.Builder(Curve.P_256, publicKey)
|
||||
.privateKey(privateKey)
|
||||
.keyUse(KeyUse.SIGNATURE)
|
||||
.keyID(keyIdString)
|
||||
.algorithm(Algorithm.parse("ES256"))
|
||||
.build()
|
||||
|
||||
return Pair(
|
||||
publicJwk.toString(),
|
||||
privateJwk.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package expo.modules.blueskyoauthclient
|
||||
|
||||
import expo.modules.kotlin.modules.Module
|
||||
import expo.modules.kotlin.modules.ModuleDefinition
|
||||
|
||||
class ExpoBlueskyOAuthClientModule : Module() {
|
||||
override fun definition() = ModuleDefinition {
|
||||
Name("ExpoBlueskyOAuthClient")
|
||||
|
||||
AsyncFunction("digest") { value: ByteArray ->
|
||||
return@AsyncFunction CryptoUtil().digest(value)
|
||||
}
|
||||
|
||||
Function("getRandomValues") { byteLength: Int ->
|
||||
return@Function CryptoUtil().getRandomValues(byteLength)
|
||||
}
|
||||
|
||||
AsyncFunction("generateKeyPair") { keyId: String? ->
|
||||
val res = CryptoUtil().generateKeyPair(keyId)
|
||||
|
||||
return@AsyncFunction mapOf(
|
||||
"publicKey" to res.first,
|
||||
"privateKey" to res.second
|
||||
)
|
||||
}
|
||||
|
||||
AsyncFunction("createJwt") { jwkString: String, headerString: String, payloadString: String ->
|
||||
return@AsyncFunction JWTUtil().createJwt(jwkString, headerString, payloadString)
|
||||
}
|
||||
|
||||
AsyncFunction("verifyJwt") { jwkString: String, tokenString: String, options: String? ->
|
||||
return@AsyncFunction JWTUtil().verifyJwt(jwkString, tokenString, options)
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package expo.modules.blueskyoauthclient
|
||||
|
||||
import com.nimbusds.jose.JWSHeader
|
||||
import com.nimbusds.jose.crypto.ECDSASigner
|
||||
import com.nimbusds.jose.crypto.ECDSAVerifier
|
||||
import com.nimbusds.jose.jwk.ECKey
|
||||
import com.nimbusds.jwt.JWTClaimsSet
|
||||
import com.nimbusds.jwt.SignedJWT
|
||||
|
||||
|
||||
class JWTUtil {
|
||||
fun createJwt(jwkString: String, headerString: String, payloadString: String): String {
|
||||
val key = ECKey.parse(jwkString)
|
||||
val header = JWSHeader.parse(headerString)
|
||||
val payload = JWTClaimsSet.parse(payloadString)
|
||||
|
||||
val signer = ECDSASigner(key)
|
||||
val jwt = SignedJWT(header, payload)
|
||||
jwt.sign(signer)
|
||||
|
||||
return jwt.serialize()
|
||||
}
|
||||
|
||||
fun verifyJwt(jwkString: String, tokenString: String, options: String?): Boolean {
|
||||
return try {
|
||||
val key = ECKey.parse(jwkString)
|
||||
val jwt = SignedJWT.parse(tokenString)
|
||||
val verifier = ECDSAVerifier(key)
|
||||
|
||||
jwt.verify(verifier)
|
||||
} catch(e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user