gerege-token-kit — FEITIAN USB токений SPM сан¶
gerege-token-kit нь FEITIAN USB токен (smart-card хэлбэрийн крипто төхөөрөмж)-тэй
локал (offline, шууд утсаар залгасан) харьцах Swift Package Manager сан. Токен дээр
түлхүүр үүсгэх, PIN-аар нэвтрэх, ECDSA/RSA гарын үсэг зурах, сертификат унших/бичих,
PKCS#10 CSR үүсгэх боломжийг өгнө.
Хараат сан байхгүй (dependency-free). Гуравдагч талын package огт ашиглахгүй — зөвхөн Apple-ийн системийн framework (
Foundation,CryptoTokenKit,CommonCrypto,os) дээр тулгуурладаг. Эх сурвалж:desktop/gerege-token-kit/Package.swift.Локал зориулалттай (local-only). Энэ сан нь зөвхөн залгасан USB токентэй шууд харьцана — RP-API эсвэл сүлжээний ямар ч дуудлага хийхгүй. Токен дээр үүссэн CSR/гарын үсгийг серверт хүргэх нь дуудагч аппын (жишээ нь macOS desktop) хариуцлага.
1. Юу хийдэг вэ¶
Сан нь хоёр түвшний хандалт өгдөг:
| Түвшин | Type | Аргачлал | Токен |
|---|---|---|---|
| Стандарт (PKCS#11) | PKCS11Module |
FEITIAN Castle middleware (libcastle*.dylib)-г dlopen-оор ачаалж C_* функц дуудна |
FEITIAN Castle FTSmartToken |
| Доод (APDU) | BioPassDriver |
ISO 7816-4 APDU-г шууд илгээж, mutual-auth дараа Secure Messaging (3DES) ашиглана | BioPass2003 / ePass2003 (EnterSafe-FIPS applet) |
Нэмэлт туслах бүрэлдэхүүн:
TokenManager—CryptoTokenKit(TKSmartCard) дээр суурилсан reader илрүүлэлт, session удирдлага.APDUCommand/APDUResponse/APDUTransceiver— APDU бүтээх/дамжуулах engine.SecureMessaging— ePass2003 3DES secure channel (mutual auth, APDU wrap/unwrap).CSR— PKCS#10 CSR (EC P-256 + ECDSA-SHA256) бүтээгч.TokenError— монгол хэл дээрх алдааны текст бүхийenum.
2. Суулгах¶
Локал path-аар нэмнэ (санг repo дотор нэг зэрэг ирдэг):
Дараа target-даа холбоно:
.target(name: "MyApp", dependencies: [
.product(name: "GeregeTokenKit", targets: ["GeregeTokenKit"])
])
Санг импортлох:
Package мэдээлэл (Package.swift):
- Нэр / product:
GeregeTokenKit - Платформ: macOS 14+, iOS 17+ (PKCS#11
dlopenзам нь бодит USB middleware шаардах тул практикт macOS-д ажиллана — доорх §5-г үзнэ үү). - swift-tools-version: 5.9
3. Public API¶
PKCS11Module (стандарт зам)¶
Эх сурвалж: Sources/GeregeTokenKit/PKCS11Module.swift.
Middleware-ийн default path-ууд (defaultLibraryPaths):
/usr/local/lib/libcastle.1.0.0.dylib, /usr/local/lib/libcastle.dylib,
/Library/OpenSC/lib/opensc-pkcs11.so.
Доод түвшний функцүүд:
| Функц | Үүрэг |
|---|---|
static open(libraryPath:) |
.dylib/.so-г dlopen-оор ачаалж C_* тэмдэгтүүдийг олно |
initialize() / finalize() |
C_Initialize / C_Finalize |
getSlotList(tokenPresent:) |
Токен залгасан slot-уудын ID |
openSession(slotId:readWrite:) / closeSession(_:) |
Session нээх/хаах |
login(session:pin:userType:) / logout(_:) |
C_Login (CKU_USER/CKU_SO) / C_Logout |
findPrivateKey(session:label:) / findPublicKey(session:label:) |
Label-аар түлхүүр олох |
signECDSA(session:privateKey:hash:) |
ECDSA гарын үсэг — буцаах: r‖s |
readECPoint(session:publicKey:) |
CKA_EC_POINT-оос raw EC цэг унших |
initToken(slotId:soPIN:label:) |
C_InitToken — factory reset + SO PIN |
initPIN(session:userPIN:) / setPIN(session:oldPIN:newPIN:) |
User PIN тогтоох/солих |
generateECKeyPair(session:label:keyID:) |
Токен дээр EC P-256 keypair үүсгэх |
writeCertificate(session:certificateDER:label:keyID:subjectDER:) |
X.509 сертификат C_CreateObject-оор хадгалах |
listObjects(session:) |
Токен дээрх бүх object-ыг TokenObjectInfo-оор жагсаах |
destroyObject(session:handle:) |
Object устгах (C_DestroyObject) |
Дээд түвшний туслах функцүүд (slot сонгох, login, logout автоматаар хийж, session өөрөө хаагдана):
| Функц | Үүрэг |
|---|---|
signECDSA(pin:keyLabel:hash:) |
PIN-аар нэвтэрч, label-аар түлхүүр олж, гарын үсэг зурна |
generateCSR(pin:keyLabel:subject:) |
Токен дээрх түлхүүрээр PKCS#10 CSR (DER+PEM) үүсгэнэ |
fullProvision(soPIN:userPIN:label:keyLabel:keyID:) |
Factory reset + SO/User PIN + EC keypair (⚠ бүх өмнөх түлхүүр устана) |
listObjects(pin:) |
Нэвтэрч бүх object жагсаах |
importCertificate(pin:label:certificateDER:keyID:) |
Сертификат импортлох |
deleteObject(pin:idHex:kind:) |
idHex+kind-ээр object устгах |
generateSigningKey(pin:label:keyID:) |
EC P-256 гарын үсгийн keypair үүсгэх |
changeUserPIN(oldPIN:newPIN:) / changeSOPIN(oldPIN:newPIN:) |
PIN солих |
unlockUserPIN(soPIN:newUserPIN:) |
Түгжигдсэн User PIN-г SO PIN-ээр тайлах |
BioPassDriver (доод/APDU зам)¶
Эх сурвалж: Sources/GeregeTokenKit/BioPassDriver.swift.
TKSmartCard-тай шууд ажилладаг (OpenSC card-epass2003.c-ийн Swift порт). Гол функцүүд:
| Функц | Үүрэг |
|---|---|
selectApplet(card:) |
EnterSafe-FIPS applet сонгох |
establishSecureSession(card:...) |
Mutual auth → Secure Messaging session тогтоох |
verifyPIN(_:reference:card:) |
User/SO PIN шалгах (буруу бол pinVerifyFailed(retriesLeft:)) |
getTokenInfo(card:) |
ATR, label, FIPS эсэх (TokenInfo) |
signECDSA(hash:card:) / signRSA(data:card:) |
Гарын үсэг |
generateECKeyPair(keyID:card:) / generateRSAKeyPair(keyID:keySize:card:) |
Түлхүүр үүсгэх (SM шаардана) |
readCertificate(fileID:card:) / writeCertificate(data:fileID:card:) |
Сертификат унших/бичих |
initializePIN(pin:puk:card:) |
Токен бүрэн initialize (erase + transport key + PKCS#15 файлын систем + PIN) |
TokenManager (reader/session)¶
Эх сурвалж: Sources/GeregeTokenKit/TokenManager.swift.
TokenManager.shared— singletongetReaderNames() -> [String],hasToken() -> BoolwithSession(readerIndex:_:)— session нээж operation гүйцэтгээд автоматаар хаанаgetATR(readerIndex:)
CSR¶
Эх сурвалж: Sources/GeregeTokenKit/CSR.swift.
CSR.Subject(commonName:organization:country:email:)CSR.buildP256(subject:publicKeyPoint:signer:)— 65 байт uncompressed EC цэг + гарын үсэг зурах closure-аас PKCS#10 CSR (DER + PEM) буцаана.
4. Ашиглалтын жишээ¶
Reader байгаа эсэхийг шалгах¶
import GeregeTokenKit
let mgr = TokenManager.shared
if mgr.hasToken() {
print("Reader-ууд:", mgr.getReaderNames())
let atr = try await mgr.getATR()
print("ATR:", bytesToHex(atr))
}
PKCS#11-ээр гарын үсэг зурах (дээд түвшин)¶
let hash = /* SHA-256 digest, 32 байт */
let p11 = try PKCS11Module.open() // libcastle*.dylib ачаална
let signature = try p11.signECDSA( // r‖s буцаана
pin: "12345678",
keyLabel: "gerege",
hash: hash
)
Токен дээрх түлхүүрээр CSR үүсгэх¶
let p11 = try PKCS11Module.open()
let subject = CSR.Subject(commonName: "Бат-Эрдэнэ", country: "MN")
let (der, pem) = try await p11.generateCSR(
pin: "12345678",
keyLabel: "gerege",
subject: subject
)
// pem-ийг CA руу илгээж сертификат авна (энэ санаас гадуур)
APDU түвшинд (BioPassDriver)¶
let driver = BioPassDriver()
try await TokenManager.shared.withSession { card in
_ = try await driver.selectApplet(card: card)
try await driver.establishSecureSession(card: card) // 3DES SM
try await driver.verifyPIN("12345678", card: card)
let sig = try await driver.signECDSA(hash: hash, card: card)
return sig
}
5. Хязгаарлалт¶
- Локал зөвхөн. Сүлжээ рүү юу ч илгээхгүй — зөвхөн залгасан токентэй харьцана.
- Платформ.
PKCS11Moduleньdlopen-оор нативе.dylibmiddleware ачаалдаг тул практикт macOS-д ашиглагдана.Package.swift-д iOS 17-г бас зарласан ч бодит USB токен - middleware байхгүй тул iOS дээр PKCS#11 зам ажиллахгүй.
- Дэмждэг токен:
- PKCS#11: FEITIAN Castle FTSmartToken (
libcastle.1.0.0.dylib); мөн OpenSCopensc-pkcs11.sodefault path-д багтсан. - APDU: BioPass2003 / ePass2003 (EnterSafe-FIPS applet).
- Крипто: EC P-256 (ECDSA-SHA256) үндсэн зам; RSA-г
BioPassDriver/PKCS11Moduleдэмждэг боловч CSR builder нь зөвхөн P-256. - Provisioning нь эвдэх үйлдэл.
fullProvision/initToken/initializePINнь токен дээрх бүх түлхүүр, сертификатыг устгана.
6. macOS desktop апптай холбоо¶
Энэ санг macOS desktop апп (eID Mongolia macOS RP клиент)
хэрэглэдэг: тухайн апп GeregeTokenKit.TokenManager.shared
болон BioPassDriver-ийг өөрийн Core/Token/TokenManager.swift-д wrap хийж, USB токеноор
PDF-д гарын үсэг зурах туршилтын урсгалыг гүйцэтгэдэг.
7. Холбоос¶
- Package:
desktop/gerege-token-kit/Package.swift - PKCS#11:
Sources/GeregeTokenKit/PKCS11Module.swift - APDU driver:
Sources/GeregeTokenKit/BioPassDriver.swift - Session/reader:
Sources/GeregeTokenKit/TokenManager.swift - APDU engine:
Sources/GeregeTokenKit/APDUEngine.swift - Secure Messaging:
Sources/GeregeTokenKit/SecureMessaging.swift - CSR builder:
Sources/GeregeTokenKit/CSR.swift - Алдаанууд:
Sources/GeregeTokenKit/TokenError.swift