react-native-dpop 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -3
- package/{Dpop.podspec → ReactNativeDPoP.podspec} +7 -3
- package/android/build.gradle +3 -3
- package/android/src/main/java/com/{dpop → reactnativedpop}/DPoPKeyStore.kt +1 -1
- package/android/src/main/java/com/{dpop/DpopModule.kt → reactnativedpop/DPoPModule.kt} +4 -4
- package/android/src/main/java/com/{dpop/DpopPackage.kt → reactnativedpop/DPoPPackage.kt} +7 -7
- package/android/src/main/java/com/{dpop → reactnativedpop}/DPoPUtils.kt +1 -1
- package/ios/DPoPKeyStore.swift +99 -0
- package/ios/DPoPModule.h +5 -0
- package/ios/DPoPModule.swift +353 -0
- package/ios/DPoPModuleBridge.mm +93 -0
- package/ios/DPoPUtils.swift +203 -0
- package/ios/KeychainKeyStore.swift +82 -0
- package/ios/SecureEnclaveKeyStore.swift +110 -0
- package/lib/module/NativeReactNativeDPoP.js +6 -0
- package/lib/module/NativeReactNativeDPoP.js.map +1 -0
- package/lib/module/index.js +13 -33
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/{NativeDpop.d.ts → NativeReactNativeDPoP.d.ts} +1 -1
- package/lib/typescript/src/NativeReactNativeDPoP.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/{NativeDpop.ts → NativeReactNativeDPoP.ts} +5 -2
- package/src/index.tsx +13 -36
- package/ios/Dpop.h +0 -5
- package/ios/Dpop.mm +0 -21
- package/lib/module/NativeDpop.js +0 -5
- package/lib/module/NativeDpop.js.map +0 -1
- package/lib/typescript/src/NativeDpop.d.ts.map +0 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTUtils.h>
|
|
3
|
+
|
|
4
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
5
|
+
#if __has_include(<ReactNativeDPoPSpec/ReactNativeDPoPSpec.h>)
|
|
6
|
+
#import <ReactNativeDPoPSpec/ReactNativeDPoPSpec.h>
|
|
7
|
+
#else
|
|
8
|
+
#import "ReactNativeDPoPSpec.h"
|
|
9
|
+
#endif
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
#if __has_include(<ReactNativeDPoP/ReactNativeDPoP-Swift.h>)
|
|
13
|
+
#import <ReactNativeDPoP/ReactNativeDPoP-Swift.h>
|
|
14
|
+
#else
|
|
15
|
+
#import "ReactNativeDPoP-Swift.h"
|
|
16
|
+
#endif
|
|
17
|
+
|
|
18
|
+
@interface RCT_EXTERN_MODULE(ReactNativeDPoP, NSObject)
|
|
19
|
+
|
|
20
|
+
RCT_EXTERN_METHOD(assertHardwareBacked:(NSString * _Nullable)alias
|
|
21
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
22
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
23
|
+
|
|
24
|
+
RCT_EXTERN_METHOD(calculateThumbprint:(NSString * _Nullable)alias
|
|
25
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
26
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
27
|
+
|
|
28
|
+
RCT_EXTERN_METHOD(deleteKeyPair:(NSString * _Nullable)alias
|
|
29
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
30
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
31
|
+
|
|
32
|
+
RCT_EXTERN_METHOD(getKeyInfo:(NSString * _Nullable)alias
|
|
33
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
34
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
35
|
+
|
|
36
|
+
RCT_EXTERN_METHOD(getPublicKeyDer:(NSString * _Nullable)alias
|
|
37
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
38
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
39
|
+
|
|
40
|
+
RCT_EXTERN_METHOD(getPublicKeyJwk:(NSString * _Nullable)alias
|
|
41
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
42
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
43
|
+
|
|
44
|
+
RCT_EXTERN_METHOD(getPublicKeyRaw:(NSString * _Nullable)alias
|
|
45
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
46
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
47
|
+
|
|
48
|
+
RCT_EXTERN_METHOD(hasKeyPair:(NSString * _Nullable)alias
|
|
49
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
50
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
51
|
+
|
|
52
|
+
RCT_EXTERN_METHOD(isBoundToAlias:(NSString *)proof
|
|
53
|
+
alias:(NSString * _Nullable)alias
|
|
54
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
55
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
56
|
+
|
|
57
|
+
RCT_EXTERN_METHOD(rotateKeyPair:(NSString * _Nullable)alias
|
|
58
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
59
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
60
|
+
|
|
61
|
+
RCT_EXTERN_METHOD(signWithDpopPrivateKey:(NSString *)payload
|
|
62
|
+
alias:(NSString * _Nullable)alias
|
|
63
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
64
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
65
|
+
|
|
66
|
+
RCT_EXTERN_METHOD(generateProof:(NSString *)htu
|
|
67
|
+
htm:(NSString *)htm
|
|
68
|
+
nonce:(NSString * _Nullable)nonce
|
|
69
|
+
accessToken:(NSString * _Nullable)accessToken
|
|
70
|
+
additional:(NSDictionary * _Nullable)additional
|
|
71
|
+
kid:(NSString * _Nullable)kid
|
|
72
|
+
jti:(NSString * _Nullable)jti
|
|
73
|
+
iat:(NSNumber * _Nullable)iat
|
|
74
|
+
alias:(NSString * _Nullable)alias
|
|
75
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
76
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
77
|
+
|
|
78
|
+
@end
|
|
79
|
+
|
|
80
|
+
@implementation ReactNativeDPoP
|
|
81
|
+
@end
|
|
82
|
+
|
|
83
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
84
|
+
@implementation ReactNativeDPoP (TurboModule)
|
|
85
|
+
|
|
86
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
87
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
88
|
+
{
|
|
89
|
+
return std::make_shared<facebook::react::NativeReactNativeDPoPSpecJSI>(params);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@end
|
|
93
|
+
#endif
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import CryptoKit
|
|
3
|
+
import Security
|
|
4
|
+
|
|
5
|
+
enum DPoPUtils {
|
|
6
|
+
static func base64UrlEncode(_ data: Data) -> String {
|
|
7
|
+
data.base64EncodedString()
|
|
8
|
+
.replacingOccurrences(of: "+", with: "-")
|
|
9
|
+
.replacingOccurrences(of: "/", with: "_")
|
|
10
|
+
.replacingOccurrences(of: "=", with: "")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static func base64UrlDecode(_ value: String) -> Data? {
|
|
14
|
+
let remainder = value.count % 4
|
|
15
|
+
let padded = remainder == 0 ? value : value + String(repeating: "=", count: 4 - remainder)
|
|
16
|
+
let base64 = padded
|
|
17
|
+
.replacingOccurrences(of: "-", with: "+")
|
|
18
|
+
.replacingOccurrences(of: "_", with: "/")
|
|
19
|
+
return Data(base64Encoded: base64)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static func sha256(_ data: Data) -> Data {
|
|
23
|
+
Data(SHA256.hash(data: data))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static func hashAccessToken(_ accessToken: String) -> String {
|
|
27
|
+
let data = Data(accessToken.utf8)
|
|
28
|
+
return base64UrlEncode(sha256(data))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static func calculateThumbprint(kty: String, crv: String, x: String, y: String) -> String {
|
|
32
|
+
let canonical = "{\"crv\":\"\(crv)\",\"kty\":\"\(kty)\",\"x\":\"\(x)\",\"y\":\"\(y)\"}"
|
|
33
|
+
return base64UrlEncode(sha256(Data(canonical.utf8)))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static func jsonData(_ object: Any) throws -> Data {
|
|
37
|
+
if #available(iOS 11.0, *) {
|
|
38
|
+
return try JSONSerialization.data(withJSONObject: object, options: [.sortedKeys])
|
|
39
|
+
}
|
|
40
|
+
return try JSONSerialization.data(withJSONObject: object, options: [])
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static func derToJose(_ derSignature: Data, partLength: Int = 32) throws -> Data {
|
|
44
|
+
let bytes = [UInt8](derSignature)
|
|
45
|
+
guard !bytes.isEmpty, bytes[0] == 0x30 else {
|
|
46
|
+
throw DPoPError.invalidDerSignature
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
var index = 1
|
|
50
|
+
let (_, seqLengthBytes) = try readDerLength(bytes, startIndex: index)
|
|
51
|
+
index += seqLengthBytes
|
|
52
|
+
|
|
53
|
+
guard index < bytes.count, bytes[index] == 0x02 else {
|
|
54
|
+
throw DPoPError.invalidDerSignature
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
index += 1
|
|
58
|
+
let (rLength, rLengthBytes) = try readDerLength(bytes, startIndex: index)
|
|
59
|
+
index += rLengthBytes
|
|
60
|
+
let rEnd = index + rLength
|
|
61
|
+
guard rEnd <= bytes.count else {
|
|
62
|
+
throw DPoPError.invalidDerSignature
|
|
63
|
+
}
|
|
64
|
+
let r = Data(bytes[index..<rEnd])
|
|
65
|
+
index = rEnd
|
|
66
|
+
|
|
67
|
+
guard index < bytes.count, bytes[index] == 0x02 else {
|
|
68
|
+
throw DPoPError.invalidDerSignature
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
index += 1
|
|
72
|
+
let (sLength, sLengthBytes) = try readDerLength(bytes, startIndex: index)
|
|
73
|
+
index += sLengthBytes
|
|
74
|
+
let sEnd = index + sLength
|
|
75
|
+
guard sEnd <= bytes.count else {
|
|
76
|
+
throw DPoPError.invalidDerSignature
|
|
77
|
+
}
|
|
78
|
+
let s = Data(bytes[index..<sEnd])
|
|
79
|
+
|
|
80
|
+
let rFixed = try toUnsignedFixedLength(r, length: partLength)
|
|
81
|
+
let sFixed = try toUnsignedFixedLength(s, length: partLength)
|
|
82
|
+
return rFixed + sFixed
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static func getPublicCoordinates(fromRawPublicKey raw: Data) throws -> (x: String, y: String) {
|
|
86
|
+
guard raw.count == 65, raw.first == 0x04 else {
|
|
87
|
+
throw DPoPError.invalidPublicKey
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let x = raw.subdata(in: 1..<33)
|
|
91
|
+
let y = raw.subdata(in: 33..<65)
|
|
92
|
+
return (base64UrlEncode(x), base64UrlEncode(y))
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static func toRawPublicKey(_ publicKey: SecKey) throws -> Data {
|
|
96
|
+
var error: Unmanaged<CFError>?
|
|
97
|
+
guard let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, &error) as Data? else {
|
|
98
|
+
throw DPoPError.securityError(error?.takeRetainedValue())
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
guard publicKeyData.count == 65, publicKeyData.first == 0x04 else {
|
|
102
|
+
throw DPoPError.invalidPublicKey
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return publicKeyData
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static func toDerPublicKey(_ publicKey: SecKey) throws -> Data {
|
|
109
|
+
let raw = try toRawPublicKey(publicKey)
|
|
110
|
+
let cryptoKey = try P256.Signing.PublicKey(x963Representation: raw)
|
|
111
|
+
return cryptoKey.derRepresentation
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static func isProofBoundToPublicKey(_ proof: String, publicKey: SecKey) throws -> Bool {
|
|
115
|
+
let parts = proof.split(separator: ".", omittingEmptySubsequences: false)
|
|
116
|
+
guard parts.count == 3 else {
|
|
117
|
+
throw DPoPError.invalidProofFormat
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
guard let headerData = base64UrlDecode(String(parts[0])) else {
|
|
121
|
+
throw DPoPError.invalidProofFormat
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let json = try JSONSerialization.jsonObject(with: headerData, options: [])
|
|
125
|
+
guard let header = json as? [String: Any],
|
|
126
|
+
let jwk = header["jwk"] as? [String: Any],
|
|
127
|
+
let kty = jwk["kty"] as? String,
|
|
128
|
+
let crv = jwk["crv"] as? String,
|
|
129
|
+
let x = jwk["x"] as? String,
|
|
130
|
+
let y = jwk["y"] as? String else {
|
|
131
|
+
throw DPoPError.invalidProofFormat
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let coordinates = try getPublicCoordinates(fromRawPublicKey: try toRawPublicKey(publicKey))
|
|
135
|
+
return kty == "EC" && crv == "P-256" && x == coordinates.x && y == coordinates.y
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private static func readDerLength(_ input: [UInt8], startIndex: Int) throws -> (Int, Int) {
|
|
139
|
+
guard startIndex < input.count else {
|
|
140
|
+
throw DPoPError.invalidDerSignature
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let first = Int(input[startIndex])
|
|
144
|
+
if (first & 0x80) == 0 {
|
|
145
|
+
return (first, 1)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let lengthBytesCount = first & 0x7F
|
|
149
|
+
guard lengthBytesCount > 0, lengthBytesCount <= 4, startIndex + lengthBytesCount < input.count else {
|
|
150
|
+
throw DPoPError.invalidDerSignature
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
var length = 0
|
|
154
|
+
for index in 0..<lengthBytesCount {
|
|
155
|
+
length = (length << 8) | Int(input[startIndex + 1 + index])
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return (length, 1 + lengthBytesCount)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private static func toUnsignedFixedLength(_ value: Data, length: Int) throws -> Data {
|
|
162
|
+
let bytes = [UInt8](value)
|
|
163
|
+
if bytes.count == length {
|
|
164
|
+
return value
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if bytes.count == length + 1, bytes.first == 0x00 {
|
|
168
|
+
return Data(bytes.dropFirst())
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if bytes.count < length {
|
|
172
|
+
return Data(repeating: 0, count: length - bytes.count) + value
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
throw DPoPError.invalidDerSignature
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
enum DPoPError: LocalizedError {
|
|
180
|
+
case invalidDerSignature
|
|
181
|
+
case invalidPublicKey
|
|
182
|
+
case invalidProofFormat
|
|
183
|
+
case keyNotFound(alias: String)
|
|
184
|
+
case notHardwareBacked(alias: String)
|
|
185
|
+
case securityError(CFError?)
|
|
186
|
+
|
|
187
|
+
var errorDescription: String? {
|
|
188
|
+
switch self {
|
|
189
|
+
case .invalidDerSignature:
|
|
190
|
+
return "Invalid DER signature format"
|
|
191
|
+
case .invalidPublicKey:
|
|
192
|
+
return "Invalid P-256 public key"
|
|
193
|
+
case .invalidProofFormat:
|
|
194
|
+
return "Invalid DPoP proof format"
|
|
195
|
+
case .keyNotFound(let alias):
|
|
196
|
+
return "Key pair not found for alias: \(alias)"
|
|
197
|
+
case .notHardwareBacked(let alias):
|
|
198
|
+
return "Key pair is not hardware-backed for alias: \(alias)"
|
|
199
|
+
case .securityError(let error):
|
|
200
|
+
return (error as Error?)?.localizedDescription ?? "Security framework error"
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Security
|
|
3
|
+
|
|
4
|
+
final class KeychainKeyStore {
|
|
5
|
+
private let service = "com.dpop.keychain"
|
|
6
|
+
|
|
7
|
+
func generateKeyPair(alias: String) throws {
|
|
8
|
+
try deleteKeyPair(alias: alias)
|
|
9
|
+
|
|
10
|
+
let tag = keyTag(alias: alias)
|
|
11
|
+
var error: Unmanaged<CFError>?
|
|
12
|
+
|
|
13
|
+
let attributes: [String: Any] = [
|
|
14
|
+
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
|
|
15
|
+
kSecAttrKeySizeInBits as String: 256,
|
|
16
|
+
kSecPrivateKeyAttrs as String: [
|
|
17
|
+
kSecAttrIsPermanent as String: true,
|
|
18
|
+
kSecAttrApplicationTag as String: tag,
|
|
19
|
+
kSecAttrLabel as String: service,
|
|
20
|
+
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
|
|
21
|
+
]
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
guard SecKeyCreateRandomKey(attributes as CFDictionary, &error) != nil else {
|
|
25
|
+
throw DPoPError.securityError(error?.takeRetainedValue())
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func deleteKeyPair(alias: String) throws {
|
|
30
|
+
let tag = keyTag(alias: alias)
|
|
31
|
+
|
|
32
|
+
let privateQuery: [String: Any] = [
|
|
33
|
+
kSecClass as String: kSecClassKey,
|
|
34
|
+
kSecAttrApplicationTag as String: tag,
|
|
35
|
+
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
let status = SecItemDelete(privateQuery as CFDictionary)
|
|
39
|
+
guard status == errSecSuccess || status == errSecItemNotFound else {
|
|
40
|
+
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func getPrivateKey(alias: String) throws -> SecKey {
|
|
45
|
+
let tag = keyTag(alias: alias)
|
|
46
|
+
let query: [String: Any] = [
|
|
47
|
+
kSecClass as String: kSecClassKey,
|
|
48
|
+
kSecAttrApplicationTag as String: tag,
|
|
49
|
+
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
|
|
50
|
+
kSecReturnRef as String: true
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
var result: CFTypeRef?
|
|
54
|
+
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
|
55
|
+
guard status == errSecSuccess, let key = result as! SecKey? else {
|
|
56
|
+
throw DPoPError.keyNotFound(alias: alias)
|
|
57
|
+
}
|
|
58
|
+
return key
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
func getPublicKey(alias: String) throws -> SecKey {
|
|
62
|
+
let privateKey = try getPrivateKey(alias: alias)
|
|
63
|
+
guard let publicKey = SecKeyCopyPublicKey(privateKey) else {
|
|
64
|
+
throw DPoPError.keyNotFound(alias: alias)
|
|
65
|
+
}
|
|
66
|
+
return publicKey
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
func hasKeyPair(alias: String) -> Bool {
|
|
70
|
+
do {
|
|
71
|
+
_ = try getPrivateKey(alias: alias)
|
|
72
|
+
_ = try getPublicKey(alias: alias)
|
|
73
|
+
return true
|
|
74
|
+
} catch {
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private func keyTag(alias: String) -> Data {
|
|
80
|
+
Data("\(service).\(alias)".utf8)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Security
|
|
3
|
+
|
|
4
|
+
final class SecureEnclaveKeyStore {
|
|
5
|
+
private let service = "com.dpop.secureenclave"
|
|
6
|
+
|
|
7
|
+
func generateKeyPair(alias: String) throws {
|
|
8
|
+
try deleteKeyPair(alias: alias)
|
|
9
|
+
|
|
10
|
+
let tag = keyTag(alias: alias)
|
|
11
|
+
var error: Unmanaged<CFError>?
|
|
12
|
+
|
|
13
|
+
guard let access = SecAccessControlCreateWithFlags(
|
|
14
|
+
nil,
|
|
15
|
+
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
|
|
16
|
+
.privateKeyUsage,
|
|
17
|
+
&error
|
|
18
|
+
) else {
|
|
19
|
+
throw DPoPError.securityError(error?.takeRetainedValue())
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let attributes: [String: Any] = [
|
|
23
|
+
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
|
|
24
|
+
kSecAttrKeySizeInBits as String: 256,
|
|
25
|
+
kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
|
|
26
|
+
kSecPrivateKeyAttrs as String: [
|
|
27
|
+
kSecAttrIsPermanent as String: true,
|
|
28
|
+
kSecAttrApplicationTag as String: tag,
|
|
29
|
+
kSecAttrLabel as String: service,
|
|
30
|
+
kSecAttrAccessControl as String: access
|
|
31
|
+
]
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
guard SecKeyCreateRandomKey(attributes as CFDictionary, &error) != nil else {
|
|
35
|
+
throw DPoPError.securityError(error?.takeRetainedValue())
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
func deleteKeyPair(alias: String) throws {
|
|
40
|
+
let tag = keyTag(alias: alias)
|
|
41
|
+
|
|
42
|
+
let privateQuery: [String: Any] = [
|
|
43
|
+
kSecClass as String: kSecClassKey,
|
|
44
|
+
kSecAttrApplicationTag as String: tag,
|
|
45
|
+
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
|
|
46
|
+
kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
let status = SecItemDelete(privateQuery as CFDictionary)
|
|
50
|
+
guard status == errSecSuccess || status == errSecItemNotFound else {
|
|
51
|
+
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
func getPrivateKey(alias: String) throws -> SecKey {
|
|
56
|
+
let tag = keyTag(alias: alias)
|
|
57
|
+
let query: [String: Any] = [
|
|
58
|
+
kSecClass as String: kSecClassKey,
|
|
59
|
+
kSecAttrApplicationTag as String: tag,
|
|
60
|
+
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
|
|
61
|
+
kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
|
|
62
|
+
kSecReturnRef as String: true
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
var result: CFTypeRef?
|
|
66
|
+
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
|
67
|
+
guard status == errSecSuccess, let key = result as! SecKey? else {
|
|
68
|
+
throw DPoPError.keyNotFound(alias: alias)
|
|
69
|
+
}
|
|
70
|
+
return key
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
func getPublicKey(alias: String) throws -> SecKey {
|
|
74
|
+
let privateKey = try getPrivateKey(alias: alias)
|
|
75
|
+
guard let publicKey = SecKeyCopyPublicKey(privateKey) else {
|
|
76
|
+
throw DPoPError.keyNotFound(alias: alias)
|
|
77
|
+
}
|
|
78
|
+
return publicKey
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
func hasKeyPair(alias: String) -> Bool {
|
|
82
|
+
do {
|
|
83
|
+
_ = try getPrivateKey(alias: alias)
|
|
84
|
+
_ = try getPublicKey(alias: alias)
|
|
85
|
+
return true
|
|
86
|
+
} catch {
|
|
87
|
+
return false
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
func isHardwareBacked(alias: String) -> Bool {
|
|
92
|
+
guard let attrs = try? attributes(alias: alias) else {
|
|
93
|
+
return false
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return (attrs[kSecAttrTokenID as String] as? String) == (kSecAttrTokenIDSecureEnclave as String)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private func attributes(alias: String) throws -> [String: Any] {
|
|
100
|
+
let privateKey = try getPrivateKey(alias: alias)
|
|
101
|
+
guard let attrs = SecKeyCopyAttributes(privateKey) as? [String: Any] else {
|
|
102
|
+
return [:]
|
|
103
|
+
}
|
|
104
|
+
return attrs
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private func keyTag(alias: String) -> Data {
|
|
108
|
+
Data("\(service).\(alias)".utf8)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { NativeModules, TurboModuleRegistry } from 'react-native';
|
|
4
|
+
const nativeDpopModule = TurboModuleRegistry.get('ReactNativeDPoP') ?? NativeModules.ReactNativeDPoP;
|
|
5
|
+
export default nativeDpopModule;
|
|
6
|
+
//# sourceMappingURL=NativeReactNativeDPoP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeModules","TurboModuleRegistry","nativeDpopModule","get","ReactNativeDPoP"],"sourceRoot":"../../src","sources":["NativeReactNativeDPoP.ts"],"mappings":";;AACA,SAASA,aAAa,EAAEC,mBAAmB,QAAQ,cAAc;AA4BjE,MAAMC,gBAAgB,GACpBD,mBAAmB,CAACE,GAAG,CAAO,iBAAiB,CAAC,IAAKH,aAAa,CAACI,eAAoC;AAEzG,eAAeF,gBAAgB","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import Dpop from "./NativeDpop.js";
|
|
5
|
-
const LINKING_ERROR = 'Dpop module nao encontrado. Verifique se o app Android foi recompilado apos adicionar o modulo nativo.';
|
|
6
|
-
function requireAndroid() {
|
|
7
|
-
if (Platform.OS !== 'android') {
|
|
8
|
-
throw new Error('react-native-dpop (MVP atual) suporta somente Android.');
|
|
9
|
-
}
|
|
10
|
-
if (!Dpop) {
|
|
11
|
-
throw new Error(LINKING_ERROR);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
3
|
+
import NativeReactNativeDPoP from "./NativeReactNativeDPoP.js";
|
|
14
4
|
export class DPoP {
|
|
15
5
|
constructor(proof, proofContext, alias) {
|
|
16
6
|
this.proof = proof;
|
|
@@ -18,51 +8,41 @@ export class DPoP {
|
|
|
18
8
|
this.alias = alias;
|
|
19
9
|
}
|
|
20
10
|
async calculateThumbprint() {
|
|
21
|
-
|
|
22
|
-
return Dpop.calculateThumbprint(this.alias ?? null);
|
|
11
|
+
return NativeReactNativeDPoP.calculateThumbprint(this.alias ?? null);
|
|
23
12
|
}
|
|
24
13
|
async getPublicKey(format) {
|
|
25
|
-
requireAndroid();
|
|
26
14
|
if (format === 'DER') {
|
|
27
|
-
return
|
|
15
|
+
return NativeReactNativeDPoP.getPublicKeyDer(this.alias ?? null);
|
|
28
16
|
}
|
|
29
17
|
if (format === 'RAW') {
|
|
30
|
-
return
|
|
18
|
+
return NativeReactNativeDPoP.getPublicKeyRaw(this.alias ?? null);
|
|
31
19
|
}
|
|
32
|
-
return
|
|
20
|
+
return NativeReactNativeDPoP.getPublicKeyJwk(this.alias ?? null);
|
|
33
21
|
}
|
|
34
22
|
async signWithDpopPrivateKey(payload) {
|
|
35
|
-
|
|
36
|
-
return Dpop.signWithDpopPrivateKey(payload, this.alias ?? null);
|
|
23
|
+
return NativeReactNativeDPoP.signWithDpopPrivateKey(payload, this.alias ?? null);
|
|
37
24
|
}
|
|
38
25
|
async isBoundToAlias(alias) {
|
|
39
|
-
|
|
40
|
-
return Dpop.isBoundToAlias(this.proof, alias ?? this.alias ?? null);
|
|
26
|
+
return NativeReactNativeDPoP.isBoundToAlias(this.proof, alias ?? this.alias ?? null);
|
|
41
27
|
}
|
|
42
28
|
static async generateProof(input) {
|
|
43
|
-
|
|
44
|
-
const result = await Dpop.generateProof(input.htu, input.htm, input.nonce ?? null, input.accessToken ?? null, input.additional ?? null, input.kid ?? null, input.jti ?? null, input.iat ?? null, input.alias ?? null);
|
|
29
|
+
const result = await NativeReactNativeDPoP.generateProof(input.htu, input.htm, input.nonce ?? null, input.accessToken ?? null, input.additional ?? null, input.kid ?? null, input.jti ?? null, input.iat ?? null, input.alias ?? null);
|
|
45
30
|
return new DPoP(result.proof, result.proofContext, input.alias);
|
|
46
31
|
}
|
|
47
32
|
static async assertHardwareBacked(alias) {
|
|
48
|
-
|
|
49
|
-
await Dpop.assertHardwareBacked(alias ?? null);
|
|
33
|
+
await NativeReactNativeDPoP.assertHardwareBacked(alias ?? null);
|
|
50
34
|
}
|
|
51
35
|
static async deleteKeyPair(alias) {
|
|
52
|
-
|
|
53
|
-
await Dpop.deleteKeyPair(alias ?? null);
|
|
36
|
+
await NativeReactNativeDPoP.deleteKeyPair(alias ?? null);
|
|
54
37
|
}
|
|
55
38
|
static async getKeyInfo(alias) {
|
|
56
|
-
|
|
57
|
-
return Dpop.getKeyInfo(alias ?? null);
|
|
39
|
+
return NativeReactNativeDPoP.getKeyInfo(alias ?? null);
|
|
58
40
|
}
|
|
59
41
|
static async hasKeyPair(alias) {
|
|
60
|
-
|
|
61
|
-
return Dpop.hasKeyPair(alias ?? null);
|
|
42
|
+
return NativeReactNativeDPoP.hasKeyPair(alias ?? null);
|
|
62
43
|
}
|
|
63
44
|
static async rotateKeyPair(alias) {
|
|
64
|
-
|
|
65
|
-
await Dpop.rotateKeyPair(alias ?? null);
|
|
45
|
+
await NativeReactNativeDPoP.rotateKeyPair(alias ?? null);
|
|
66
46
|
}
|
|
67
47
|
}
|
|
68
48
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["NativeReactNativeDPoP","DPoP","constructor","proof","proofContext","alias","calculateThumbprint","getPublicKey","format","getPublicKeyDer","getPublicKeyRaw","getPublicKeyJwk","signWithDpopPrivateKey","payload","isBoundToAlias","generateProof","input","result","htu","htm","nonce","accessToken","additional","kid","jti","iat","assertHardwareBacked","deleteKeyPair","getKeyInfo","hasKeyPair","rotateKeyPair"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,qBAAqB,MAAM,4BAAyB;AAoD3D,OAAO,MAAMC,IAAI,CAAC;EAKRC,WAAWA,CAACC,KAAa,EAAEC,YAA8B,EAAEC,KAAc,EAAE;IACjF,IAAI,CAACF,KAAK,GAAGA,KAAK;IAClB,IAAI,CAACC,YAAY,GAAGA,YAAY;IAChC,IAAI,CAACC,KAAK,GAAGA,KAAK;EACpB;EAEA,MAAaC,mBAAmBA,CAAA,EAAoB;IAClD,OAAON,qBAAqB,CAACM,mBAAmB,CAAC,IAAI,CAACD,KAAK,IAAI,IAAI,CAAC;EACtE;EAEA,MAAaE,YAAYA,CAACC,MAAuB,EAA+B;IAC9E,IAAIA,MAAM,KAAK,KAAK,EAAE;MACpB,OAAOR,qBAAqB,CAACS,eAAe,CAAC,IAAI,CAACJ,KAAK,IAAI,IAAI,CAAC;IAClE;IACA,IAAIG,MAAM,KAAK,KAAK,EAAE;MACpB,OAAOR,qBAAqB,CAACU,eAAe,CAAC,IAAI,CAACL,KAAK,IAAI,IAAI,CAAC;IAClE;IAEA,OAAOL,qBAAqB,CAACW,eAAe,CAAC,IAAI,CAACN,KAAK,IAAI,IAAI,CAAC;EAClE;EAEA,MAAaO,sBAAsBA,CAACC,OAAe,EAAmB;IACpE,OAAOb,qBAAqB,CAACY,sBAAsB,CAACC,OAAO,EAAE,IAAI,CAACR,KAAK,IAAI,IAAI,CAAC;EAClF;EAEA,MAAaS,cAAcA,CAACT,KAAc,EAAoB;IAC5D,OAAOL,qBAAqB,CAACc,cAAc,CAAC,IAAI,CAACX,KAAK,EAAEE,KAAK,IAAI,IAAI,CAACA,KAAK,IAAI,IAAI,CAAC;EACtF;EAEA,aAAoBU,aAAaA,CAACC,KAAyB,EAAiB;IAC1E,MAAMC,MAAM,GAAI,MAAMjB,qBAAqB,CAACe,aAAa,CACvDC,KAAK,CAACE,GAAG,EACTF,KAAK,CAACG,GAAG,EACTH,KAAK,CAACI,KAAK,IAAI,IAAI,EACnBJ,KAAK,CAACK,WAAW,IAAI,IAAI,EACzBL,KAAK,CAACM,UAAU,IAAI,IAAI,EACxBN,KAAK,CAACO,GAAG,IAAI,IAAI,EACjBP,KAAK,CAACQ,GAAG,IAAI,IAAI,EACjBR,KAAK,CAACS,GAAG,IAAI,IAAI,EACjBT,KAAK,CAACX,KAAK,IAAI,IACjB,CAAyB;IAEzB,OAAO,IAAIJ,IAAI,CAACgB,MAAM,CAACd,KAAK,EAAEc,MAAM,CAACb,YAAY,EAAEY,KAAK,CAACX,KAAK,CAAC;EACjE;EAEA,aAAoBqB,oBAAoBA,CAACrB,KAAc,EAAiB;IACtE,MAAML,qBAAqB,CAAC0B,oBAAoB,CAACrB,KAAK,IAAI,IAAI,CAAC;EACjE;EAEA,aAAoBsB,aAAaA,CAACtB,KAAc,EAAiB;IAC/D,MAAML,qBAAqB,CAAC2B,aAAa,CAACtB,KAAK,IAAI,IAAI,CAAC;EAC1D;EAEA,aAAoBuB,UAAUA,CAACvB,KAAc,EAAwB;IACnE,OAAOL,qBAAqB,CAAC4B,UAAU,CAACvB,KAAK,IAAI,IAAI,CAAC;EACxD;EAEA,aAAoBwB,UAAUA,CAACxB,KAAc,EAAoB;IAC/D,OAAOL,qBAAqB,CAAC6B,UAAU,CAACxB,KAAK,IAAI,IAAI,CAAC;EACxD;EAEA,aAAoByB,aAAaA,CAACzB,KAAc,EAAiB;IAC/D,MAAML,qBAAqB,CAAC8B,aAAa,CAACzB,KAAK,IAAI,IAAI,CAAC;EAC1D;AACF","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeReactNativeDPoP.d.ts","sourceRoot":"","sources":["../../../src/NativeReactNativeDPoP.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAE9E,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACxD,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7D,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/E,aAAa,CACX,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,UAAU,EAAE,YAAY,GAAG,IAAI,EAC/B,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO,CAAC,YAAY,CAAC,CAAC;CAC1B;wBAKkC,IAAI;AAAvC,wBAAwC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEhD,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,IAAI,CAAC;IACV,GAAG,EAAE,OAAO,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEpD,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAOF,qBAAa,IAAI;IACf,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,SAAgB,KAAK,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAgB,YAAY,EAAE,gBAAgB,CAAC;IAE/C,OAAO;IAMM,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC;IAItC,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC;IAWlE,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIxD,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAIzC,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;WAgBvD,oBAAoB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAInD,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAI5C,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;WAIhD,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAI5C,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGjE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-dpop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "React Native library for DPoP proof generation and key management.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"android",
|
|
@@ -110,11 +110,11 @@
|
|
|
110
110
|
]
|
|
111
111
|
},
|
|
112
112
|
"codegenConfig": {
|
|
113
|
-
"name": "
|
|
113
|
+
"name": "ReactNativeDPoPSpec",
|
|
114
114
|
"type": "modules",
|
|
115
115
|
"jsSrcsDir": "src",
|
|
116
116
|
"android": {
|
|
117
|
-
"javaPackageName": "com.
|
|
117
|
+
"javaPackageName": "com.reactnativedpop"
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TurboModule } from 'react-native';
|
|
2
|
-
import { TurboModuleRegistry } from 'react-native';
|
|
2
|
+
import { NativeModules, TurboModuleRegistry } from 'react-native';
|
|
3
3
|
import type { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes';
|
|
4
4
|
|
|
5
5
|
export interface Spec extends TurboModule {
|
|
@@ -27,4 +27,7 @@ export interface Spec extends TurboModule {
|
|
|
27
27
|
): Promise<UnsafeObject>;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
const nativeDpopModule =
|
|
31
|
+
TurboModuleRegistry.get<Spec>('ReactNativeDPoP') ?? (NativeModules.ReactNativeDPoP as Spec | undefined);
|
|
32
|
+
|
|
33
|
+
export default nativeDpopModule as Spec;
|