Skip to content

Commit 8bc1c45

Browse files
committed
Dropped 3rd-party dependencies
1 parent dd1ebdf commit 8bc1c45

File tree

11 files changed

+210
-93
lines changed

11 files changed

+210
-93
lines changed

Package.resolved

Lines changed: 0 additions & 32 deletions
This file was deleted.

Package.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,25 @@ let package = Package(
88
products: [
99
.library(name: "IDKit", targets: ["IDKit"]),
1010
],
11-
dependencies: [
12-
.package(url: "https://github.com/attaswift/BigInt.git", from: "5.3.0"),
13-
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "1.9.0"),
14-
.package(url: "https://github.com/apple/swift-crypto.git", "1.0.0"..<"4.0.0"),
15-
],
11+
dependencies: [],
1612
targets: [
13+
.target(
14+
name: "Keccak",
15+
path: "./Sources/Keccak",
16+
publicHeadersPath: "include"
17+
),
1718
.target(
1819
name: "IDKit",
1920
dependencies: [
20-
.product(name: "BigInt", package: "BigInt"),
21-
.product(name: "Crypto", package: "swift-crypto"),
22-
.product(name: "CryptoSwift", package: "CryptoSwift"),
21+
"Keccak",
2322
],
2423
path: "./Sources/IDKit",
2524
swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]
2625
),
27-
.testTarget(
28-
name: "IDKitTests",
29-
dependencies: ["IDKit"]
30-
)
26+
.testTarget(
27+
name: "IDKitTests",
28+
dependencies: ["IDKit"],
29+
swiftSettings: [.enableExperimentalFeature("SwiftTesting")]
30+
),
3131
]
3232
)

Sources/IDKit/BridgeClient.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@preconcurrency import Crypto
1+
@preconcurrency import CryptoKit
22
import Foundation
33
#if canImport(FoundationNetworking)
44
import FoundationNetworking

Sources/IDKit/BridgeClientTypes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Crypto
1+
import CryptoKit
22
import Foundation
33

44
/// The error returned by the World App.

Sources/IDKit/Extensions/Encodable+encrypt.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Crypto
1+
import CryptoKit
22
import Foundation
33

44
extension Encodable {

Sources/IDKit/KeccakHasher.swift

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import CryptoKit
2+
import Keccak
3+
4+
struct SHA3Keccak256: HashFunction {
5+
struct SHA3Keccak256Digest: CryptoKit.Digest, Sendable {
6+
static let byteCount = SHA3Keccak256.digestByteCount
7+
8+
fileprivate let bytes: [UInt8]
9+
10+
init(bytes: [UInt8]) {
11+
precondition(bytes.count == Self.byteCount, "Keccak digest must be 32 bytes")
12+
self.bytes = bytes
13+
}
14+
15+
var count: Int { bytes.count }
16+
17+
func makeIterator() -> Array<UInt8>.Iterator {
18+
bytes.makeIterator()
19+
}
20+
21+
func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
22+
try bytes.withUnsafeBytes(body)
23+
}
24+
25+
var description: String {
26+
bytes.map { String(format: "%02x", $0) }.joined()
27+
}
28+
29+
var debugDescription: String {
30+
"SHA3Keccak256Digest(\(description))"
31+
}
32+
33+
static func == (lhs: SHA3Keccak256Digest, rhs: SHA3Keccak256Digest) -> Bool {
34+
lhs.bytes == rhs.bytes
35+
}
36+
37+
func hash(into hasher: inout Hasher) {
38+
hasher.combine(bytes.count)
39+
for chunk in bytes {
40+
hasher.combine(chunk)
41+
}
42+
}
43+
}
44+
45+
typealias Digest = SHA3Keccak256Digest
46+
47+
static let blockByteCount = 136
48+
static let digestByteCount = 32
49+
static let maxMessageLength = Int.max
50+
51+
private var buffer = [UInt8]()
52+
53+
init() {}
54+
55+
mutating func update(bufferPointer: UnsafeRawBufferPointer) {
56+
guard !bufferPointer.isEmpty else {
57+
return
58+
}
59+
precondition(buffer.count <= Self.maxMessageLength - bufferPointer.count, "Message too long")
60+
buffer.append(contentsOf: bufferPointer)
61+
}
62+
63+
func finalize() -> Digest {
64+
Digest(bytes: Self.computeDigest(for: buffer))
65+
}
66+
67+
private static func computeDigest(for message: [UInt8]) -> [UInt8] {
68+
var digest = [UInt8](repeating: 0, count: digestByteCount)
69+
70+
digest.withUnsafeMutableBufferPointer { outputBuffer in
71+
guard let outputBaseAddress = outputBuffer.baseAddress else {
72+
return
73+
}
74+
75+
message.withUnsafeBufferPointer { inputBuffer in
76+
keccak256_hash(inputBuffer.baseAddress, inputBuffer.count, outputBaseAddress)
77+
}
78+
}
79+
80+
return digest
81+
}
82+
}

Sources/IDKit/Session.swift

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import BigInt
21
import Foundation
3-
import CryptoSwift
42

53
public enum SessionError: Error, CustomDebugStringConvertible {
64
case incorrectDataEncoding(String)
@@ -92,7 +90,7 @@ public extension Session where Response == Proof {
9290
let payload = CreateRequestPayload(
9391
appID: appID,
9492
action: action,
95-
signal: try encodeSignal(signal),
93+
signal: encodeSignal(signal),
9694
actionDescription: actionDescription,
9795
verificationLevel: verificationLevel
9896
)
@@ -131,7 +129,7 @@ public extension Session where Response == CredentialCategoryProofResponse {
131129
let payload = CredentialCategoryRequestPayload(
132130
appID: appID,
133131
action: action,
134-
signal: try encodeSignal(signal),
132+
signal: encodeSignal(signal),
135133
actionDescription: actionDescription,
136134
credentialCategories: credentialCategories
137135
)
@@ -140,18 +138,15 @@ public extension Session where Response == CredentialCategoryProofResponse {
140138
}
141139
}
142140

143-
func encodeSignal(_ signal: String) throws -> String {
144-
// Encode signal data
145-
let signalData = signal.data(using: .utf8) ?? Data()
146-
147-
// Convert Data to bytes array and use SHA3 with keccak256 variant
148-
let bytes = [UInt8](signalData)
149-
let hash = SHA3(variant: .keccak256).calculate(for: bytes)
150-
151-
// Convert to hex string
152-
let hashData = Data(hash)
153-
let hexString = String(BigUInt(hashData) >> 8, radix: 16)
154-
// Pad with leading zeros to ensure 64 characters
155-
let paddedHex = String(repeating: "0", count: max(0, 64 - hexString.count)) + hexString
141+
func encodeSignal(_ signal: String) -> String {
142+
// Encode signal data and compute Keccak-256
143+
let hash = SHA3Keccak256.hash(data: Data(signal.utf8))
144+
145+
// Drop the least-significant byte to match the legacy BigInt >> 8 behavior
146+
let truncated = Array(hash).dropLast()
147+
let hex = truncated.map { String(format: "%02x", $0) }.joined()
148+
149+
// Pad with leading zeros to ensure a 32-byte (64 hex chars) string
150+
let paddedHex = String(repeating: "0", count: max(0, 64 - hex.count)) + hex
156151
return "0x" + paddedHex
157152
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Sourced from https://github.com/XKCP/XKCP/blob/e774b9606029ab79dd787252841816a3c60ef8fe/Standalone/CompactFIPS202/C/Keccak-more-compact.c
2+
#define FOR(i,n) for(i=0; i<n; ++i)
3+
typedef unsigned char u8;
4+
typedef unsigned long long int u64;
5+
typedef unsigned int ui;
6+
7+
void Keccak(ui r, ui c, const u8 *in, u64 inLen, u8 sfx, u8 *out, u64 outLen);
8+
void FIPS202_SHAKE128(const u8 *in, u64 inLen, u8 *out, u64 outLen) { Keccak(1344, 256, in, inLen, 0x1F, out, outLen); }
9+
void FIPS202_SHAKE256(const u8 *in, u64 inLen, u8 *out, u64 outLen) { Keccak(1088, 512, in, inLen, 0x1F, out, outLen); }
10+
void FIPS202_SHA3_224(const u8 *in, u64 inLen, u8 *out) { Keccak(1152, 448, in, inLen, 0x06, out, 28); }
11+
void FIPS202_SHA3_256(const u8 *in, u64 inLen, u8 *out) { Keccak(1088, 512, in, inLen, 0x06, out, 32); }
12+
void FIPS202_SHA3_384(const u8 *in, u64 inLen, u8 *out) { Keccak(832, 768, in, inLen, 0x06, out, 48); }
13+
void FIPS202_SHA3_512(const u8 *in, u64 inLen, u8 *out) { Keccak(576, 1024, in, inLen, 0x06, out, 64); }
14+
15+
int LFSR86540(u8 *R) { (*R)=((*R)<<1)^(((*R)&0x80)?0x71:0); return ((*R)&2)>>1; }
16+
#define ROL(a,o) ((((u64)a)<<o)^(((u64)a)>>(64-o)))
17+
static u64 load64(const u8 *x) { ui i; u64 u=0; FOR(i,8) { u<<=8; u|=x[7-i]; } return u; }
18+
static void store64(u8 *x, u64 u) { ui i; FOR(i,8) { x[i]=u; u>>=8; } }
19+
static void xor64(u8 *x, u64 u) { ui i; FOR(i,8) { x[i]^=u; u>>=8; } }
20+
#define rL(x,y) load64((u8*)s+8*(x+5*y))
21+
#define wL(x,y,l) store64((u8*)s+8*(x+5*y),l)
22+
#define XL(x,y,l) xor64((u8*)s+8*(x+5*y),l)
23+
void KeccakF1600(void *s)
24+
{
25+
ui r,x,y,i,j,Y; u8 R=0x01; u64 C[5],D;
26+
for(i=0; i<24; i++) {
27+
/*θ*/ FOR(x,5) C[x]=rL(x,0)^rL(x,1)^rL(x,2)^rL(x,3)^rL(x,4); FOR(x,5) { D=C[(x+4)%5]^ROL(C[(x+1)%5],1); FOR(y,5) XL(x,y,D); }
28+
/*ρπ*/ x=1; y=r=0; D=rL(x,y); FOR(j,24) { r+=j+1; Y=(2*x+3*y)%5; x=y; y=Y; C[0]=rL(x,y); wL(x,y,ROL(D,r%64)); D=C[0]; }
29+
/*χ*/ FOR(y,5) { FOR(x,5) C[x]=rL(x,y); FOR(x,5) wL(x,y,C[x]^((~C[(x+1)%5])&C[(x+2)%5])); }
30+
/*ι*/ FOR(j,7) if (LFSR86540(&R)) XL(0,0,(u64)1<<((1<<j)-1));
31+
}
32+
}
33+
void Keccak(ui r, ui c, const u8 *in, u64 inLen, u8 sfx, u8 *out, u64 outLen)
34+
{
35+
/*initialize*/ u8 s[200]; ui R=r/8; ui i,b=0; FOR(i,200) s[i]=0;
36+
/*absorb*/ while(inLen>0) { b=(inLen<R)?inLen:R; FOR(i,b) s[i]^=in[i]; in+=b; inLen-=b; if (b==R) { KeccakF1600(s); b=0; } }
37+
/*pad*/ s[b]^=sfx; if((sfx&0x80)&&(b==(R-1))) KeccakF1600(s); s[R-1]^=0x80; KeccakF1600(s);
38+
/*squeeze*/ while(outLen>0) { b=(outLen<R)?outLen:R; FOR(i,b) out[i]=s[i]; out+=b; outLen-=b; if(outLen>0) KeccakF1600(s); }
39+
}

Sources/Keccak/KeccakWrapper.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "KeccakWrapper.h"
2+
3+
void Keccak(unsigned int rate,
4+
unsigned int capacity,
5+
const unsigned char *input,
6+
unsigned long long int inputByteLen,
7+
unsigned char delimitedSuffix,
8+
unsigned char *output,
9+
unsigned long long int outputByteLen);
10+
11+
void keccak256_hash(const uint8_t * _Nullable input, size_t inputByteLen, uint8_t *output)
12+
{
13+
static const uint8_t zero = 0;
14+
const unsigned char *message = (inputByteLen == 0 && input == NULL) ? &zero : input;
15+
Keccak(1088, 512, message, (unsigned long long int)inputByteLen, 0x01, output, 32);
16+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef KECCAK_WRAPPER_H
2+
#define KECCAK_WRAPPER_H
3+
4+
#include <stddef.h>
5+
#include <stdint.h>
6+
7+
#ifdef __cplusplus
8+
extern "C" {
9+
#endif
10+
11+
void keccak256_hash(const uint8_t * _Nullable input, size_t inputByteLen, uint8_t * _Nonnull output);
12+
13+
#ifdef __cplusplus
14+
}
15+
#endif
16+
17+
#endif

0 commit comments

Comments
 (0)