In meiner statischen Bibliothek habe ich eine Lizenzdatei. Was ich sicherstellen möchte, wurde von mir selbst generiert (und wurde nicht verändert). Die Idee war also, eine RSA-Signatur von dem zu verwenden, was ich gelesen habe.Überprüfen der RSA-Signatur iOS
Ich habe im Internet geschaut und das ist, was ich kam mit:
Erstens: Die Erzeugung der privaten Schlüssel und selbstsignierte Zertifikate mit den Informationen, die ich here gefunden.
// Generate private key
openssl genrsa -out private_key.pem 2048 -sha256
// Generate certificate request
openssl req -new -key private_key.pem -out certificate_request.pem -sha256
// Generate public certificate
openssl x509 -req -days 2000 -in certificate_request.pem -signkey private_key.pem -out certificate.pem -sha256
// Convert it to cer format so iOS kan work with it
openssl x509 -outform der -in certificate.pem -out certificate.cer -sha256
Danach erstelle ich eine Lizenzdatei (mit einem Datum und einer App Kennung als Inhalt) und eine Signatur für diese Datei wie so erzeugen, die auf der Grundlage der Informationen gefunden here:
// Store the sha256 of the licence in a file
openssl dgst -sha256 licence.txt > hash
// And generate a signature file for that hash with the private key generated earlier
openssl rsautl -sign -inkey private_key.pem -keyform PEM -in hash > signature.sig
Was ich denke, alles funktioniert gut. Ich bekomme keine Fehler und bekomme die Schlüssel und Zertifikate und andere Dateien wie erwartet.
Als nächstes kopiere ich certificate.cer
, signature.sig
und license.txt
zu meiner Anwendung.
Jetzt möchte ich überprüfen, ob die Signatur von mir signiert wurde und für die Lizenz.txt gültig ist. Ich fand es ziemlich schwer, keine guten Beispiele zu finden, aber das ist, was ich habe zur Zeit:
Die Seucyrity.Framework
Ich fand heraus, verwendet ein SecKeyRef
ein RSA-Schlüssel/Zertifikat zu referenzieren und SecKeyRawVerify
eine Signatur zu verifizieren.
Ich habe die folgende Methode, um den öffentlichen Schlüssel aus einer Datei zu laden.
- (SecKeyRef)publicKeyFromFile:(NSString *) path
{
NSData *myCertData = [[NSFileManager defaultManager] contentsAtPath:path];
CFDataRef myCertDataRef = (__bridge CFDataRef) myCertData;
SecCertificateRef cert = SecCertificateCreateWithData (kCFAllocatorDefault, myCertDataRef);
CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **) &cert, 1, NULL);
SecPolicyRef policy = SecPolicyCreateBasicX509();
SecTrustRef trust;
SecTrustCreateWithCertificates(certs, policy, &trust);
SecTrustResultType trustResult;
SecTrustEvaluate(trust, &trustResult);
SecKeyRef pub_key_leaf = SecTrustCopyPublicKey(trust);
if (trustResult == kSecTrustResultRecoverableTrustFailure)
{
NSLog(@"I think this is the problem");
}
return pub_key_leaf;
}
Die basiert auf this SO post.
Für die Signaturprüfung fand ich die folgende Funktion
BOOL PKCSVerifyBytesSHA256withRSA(NSData* plainData, NSData* signature, SecKeyRef publicKey)
{
size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey);
const void* signedHashBytes = [signature bytes];
size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;
uint8_t* hashBytes = malloc(hashBytesSize);
if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {
return nil;
}
OSStatus status = SecKeyRawVerify(publicKey,
kSecPaddingPKCS1SHA256,
hashBytes,
hashBytesSize,
signedHashBytes,
signedHashBytesSize);
return status == errSecSuccess;
}
die sich von here
In meinem Projekt der Code wie ich nenne so genommen wird:
es// Get the licence data
NSString *licencePath = [[NSBundle mainBundle] pathForResource:@"licence" ofType:@"txt"];
NSData *data = [[NSFileManager defaultManager] contentsAtPath:licencePath];
// Get the signature data
NSString *signaturePath = [[NSBundle mainBundle] pathForResource:@"signature" ofType:@"sig"];
NSData *signature = [[NSFileManager defaultManager] contentsAtPath:signaturePath];
// Get the public key
NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"];
SecKeyRef publicKey = [self publicKeyFromFile:publicKeyPath];
// Check if the signature is valid with this public key for this data
BOOL result = PKCSVerifyBytesSHA256withRSA(data, signature, publicKey);
if (result)
{
NSLog(@"Alright All good!");
}
else
{
NSLog(@"Something went wrong!");
}
Aktuell sagt immer : "Etwas ist schief gelaufen!" obwohl ich mir nicht sicher bin was. Ich habe herausgefunden, dass das Vertrauen in der Methode resultiert, die den öffentlichen Schlüssel gleich kSecTrustResultRecoverableTrustFailure
holt, was ich denke, ist das Problem. In der Apple documentation fand ich, dass das Ergebnis eines Zertifikats sein könnte, das abgelaufen ist. Obwohl das hier nicht der Fall zu sein scheint. Aber vielleicht stimmt etwas nicht mit der Art und Weise, wie ich mein Zertifikat erstelle?
Meine Frage läuft darauf hinaus, was mache ich falsch, und wie könnte ich das beheben? Ich finde die Dokumentation zu diesem Thema sehr spärlich und schwer zu lesen.
Ich habe uploaded ein iOS-Projekt mit generierten Zertifikaten und dem hier referenzierten Code. Vielleicht könnte das nützlich sein.
Wenn man sich anschaut, 3- Listing In der Dokumentation, auf die Sie verwiesen haben, sehen Sie 5 "AllStatusBits". Können Sie herausfinden, was die Statusbits sind, wenn Sie auf diesen Fehler stoßen? –
Hallo, wenn ich versuche, diesen Code zu integrieren, ist einer der ersten Fehler, dass der Typ 'CSSM_TP_APPLE_CERT_STATUS' von' AllStatusBits' unbekannt ist und ich kann keine funktionierende Header-Datei finden, die diesen Typ enthält. Im Internet habe ich festgestellt, dass es "#import" sein könnte, aber das gibt es (nicht mehr) auf iOS. - Ich habe mein Projekt mit Code und Zertifikaten hochgeladen (http://up.indev.nl/RTR4y0Ou0L.zip), vielleicht hilft das. –
Matthijn
Ja, ich habe es einfach überprüft, aber ich habe [bereits] (http://up.indev.nl/C5OHOFziPO.png) das Sicherheitsframework hinzugefügt. Vielleicht wurde das woanders in einer iOS-Version verschoben? – Matthijn