VirgilFoundation 2.0.0

VirgilFoundation 2.0.0

测试已测试
语言语言 Objective C++Objective C++
许可证 BSD
发布最后发布2018年1月

SanjoDeundiakSergey Seroshtan 维护。



  • 作者:
  • Pavlo Gorb

Virgil Foundation Objective-C/Swift

简介

这是一个基本的底层框架,允许执行一些最重要的安全操作。此框架被用于其他高级 Virgil 框架、库和应用程序中。它也可以作为任何关注安全的独立基本库。

安装

如果您打算使用任何高级 Virgil 框架,例如 VirgilSDK,那么您不需要直接安装 VirgilFoundation。它将随高级框架的所有必需依赖项一起安装。

本章的其余部分描述了如何直接安装 VirgilFoundation 框架。使用 CocoaPods 安装和维护 VirgilFoundation 框架是针对 Objective-C/Swift 应用程序的最简单和推荐方式。

  • 首先,您需要在您的计算机上安装 CocoaPods。您可以在终端中执行以下行来完成此操作
$ sudo gem install cocoapods

CocoaPods 是用 Ruby 构建的,并且可以通过 OS X 上默认的 Ruby 安装。

  • 打开 Xcode 并创建一个新的项目(在 Xcode 菜单中:文件 -> 新建 -> 项目),或者使用以下方式导航到现有的 Xcode 项目
$ cd <Path to Xcode project folder>
  • 在 Xcode 项目的文件夹中创建一个新文件,给它命名为 Podfile(带大写的 P,不带任何扩展名)。以下示例展示了如何为一个 iOS 应用程序编写 Podfile。如果您计划使用其他平台,该过程将非常相似。您只需要将平台更改为相应的值。您可以在 这里 找到有关平台值的信息。
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!

target '<Put your Xcode target name here>' do
    pod 'VirgilFoundation'
end
  • 回到您的终端窗口,并执行以下行
$ pod install
  • 关闭 Xcode 项目(如果它仍然开放)。为了任何进一步的开发目的,您应该使用 CocoaPods 为您创建的 .xcworkspace 文件。

到此为止,您应该能够在代码中使用 Virgil 密码功能。下面列出了最常见任务的一些示例。如果您在 CocoaPods 安装过程中遇到任何问题,请尝试在 cocoapods.org 找到更多信息。

Swift笔记

尽管VirgilFoundation使用Objective-C作为其主要语言,但在Swift应用程序中使用它却非常简单。按照入门部分描述安装VirgilFoundation后,需要执行以下操作。

  • 在Swift项目中创建一个新的头文件。
  • 将其命名为类似BridgingHeader.h的东西。
  • 在该文件中放入以下行
@import VirgilFoundation;
  • 在Xcode构建设置中找到名为Objective-C桥接头的设置,并将路径设置为您的BridgingHeader.h文件。请注意,此路径相对于您的Xcode项目文件夹。

您可以在此处找到有关在同一个项目中使用Objective-C和Swift的更多信息。

使用场景

以下您可以找到使用VirgilFoundation框架能够执行的大部分常见任务的示例。

创建一个新的密钥对

应该使用VSSKeyPair实例来生成一对密钥。可以生成一个受密码保护的私钥。如果没有提供密码,私钥将以纯数据形式生成。

Objective-C
//...
VSSKeyPair *keyPair = [[VSSKeyPair alloc] initWithPassword:<#Password or nil#>];
NSString *publicKey = [[NSString alloc] initWithData:keyPair.publicKey encoding:NSUTF8StringEncoding];
NSLog(@"%@", publicKey);
NSString *privateKey = [[NSString alloc] initWithData:keyPair.privateKey encoding:NSUTF8StringEncoding];
NSLog(@"%@", privateKey);
//...
Swift
//...
let keyPair = VSSKeyPair(password:<#Password or nil#>)
println(NSString(data: keyPair.publicKey(), encoding: NSUTF8StringEncoding))
println(NSString(data: keyPair.privateKey(), encoding: NSUTF8StringEncoding))
//...

加密和解密数据

VSSCryptor对象可以执行两种加密/解密方式

  • 基于密钥的加密/解密。
  • 基于密码的加密/解密。

基于密钥的加密

Objective-C
//...
// Assuming that we have some initial string message.
NSString *message = @"This is a secret message which should be encrypted.";
// Convert it to the NSData
NSData *toEncrypt = [message dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO];
// Assuming that we have some key pair generated earlier.
// Create a new VSSCryptor instance
VSSCryptor *cryptor = [[VSSCryptor alloc] init];
// Now we should add a key recipient
NSError *error = nil;
if (![cryptor addKeyRecipient:<# Recipient ID #> publicKey:<# keyPair.publicKey #> error:&error]) {
    NSLog(@"Error adding key recipient: %@", [error localizedDescription]);
    return;
}
// And now we can easily encrypt the plain data
NSData *encryptedData = [cryptor encryptData:toEncrypt embedContentInfo:YES error:&error];
if (error != nil) {
    NSLog(@"Error encrypting data: %@", [error localizedDescription]);
    return;
}
//...
Swift
//...
// Assuming that we have some initial string message.
let message = NSString(string: "This is a secret message which should be encrypted.")
// Convert it to the NSData
if let toEncrypt = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
    // Assuming that we have some key pair generated earlier.
    // Create a new VSSCryptor instance
    let cryptor = VSSCryptor()
    // Now we should add a key recipient
    var encryptedData = NSData()
    do {
        try cryptor.addKeyRecipient(<# Recipient ID #>, publicKey: <# keyPair.publicKey() #>, error: ())
        // And now we can easily encrypt the plain data
        encryptedData = try cryptor.encryptData(toEncrypt, embedContentInfo: true, error: ())
    }
    catch let error as NSError {
        print("Error: \(error.localizedDescription)")
    }
    //...
}
//...

基于密钥的解密

Objective-C
//...
// Assuming that we have received some key-based encrypted data.
// Assuming that we have some key pair generated earlier.
// Create a new VSSCryptor instance
VSSCryptor *decryptor = [[VSSCryptor alloc] init];
// Decrypt data
NSError *error = nil;
NSData *plainData = [decryptor decryptData:<# NSData containing encrypted data #> recipientId:<# Recipient ID #> privateKey:<# keyPair.privateKey #> keyPassword:<# Private key password or nil #> error:&error];
if (error != nil) {
    NSLog(@"Error decrypting data: %@", [error localizedDescription]);
    return;
}
// Compose initial message from the plain decrypted data
NSString *initialMessage = [[NSString alloc] initWithData:plainData encoding:NSUTF8StringEncoding];
//...
Swift
//...
// Assuming that we have received some key-based encrypted data.
// Assuming that we have some key pair generated earlier.
// Create a new VSSCryptor instance
let decryptor = VSSCryptor()
// Decrypt data
do {
    let plainData = try decryptor.decryptData(<# NSData with encrypted data #>, recipientId: <# Recipient ID #>, privateKey: <# keyPair.privateKey() #>, keyPassword: <# Private key password or nil #>, error: ())
    // Compose initial message from the plain decrypted data
    if let initialMessage = NSString(data: plainData, encoding: NSUTF8StringEncoding) {
        // Use initialMessage.
        //...
    }
}
catch let error as NSError {
    print("Error: \(error.localizedDescription)")
}
//...

基于密码的加密

Objective-C
//...
// Assuming that we have some initial string message.
NSString *message = @"This is a secret message which should be encrypted with password-based encryption.";
// Convert it to the NSData
NSData *toEncrypt = [message dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO];
// Assuming that we have some key pair generated earlier.
// Create a new VSSCryptor instance
VSSCryptor *cryptor = [[VSSCryptor alloc] init];
NSError *error = nil;
if (![cryptor addPasswordRecipient:<# Password to encrypt data with #> error:&error]) {
    NSLog(@"Error adding password recipient: %@", [error localizedDescription]);
    return;
}
// And now we can encrypt the plain data
NSData *encryptedData = [cryptor encryptData:toEncrypt embedContentInfo:YES error:&error];
if (error != nil) {
    NSLog(@"Error encrypting data: %@", [error localizedDescription]);
    return;
}
//...
Swift
//...
// Assuming that we have some initial string message.
let message = NSString(string: "This is a secret message which should be encrypted.")
// Convert it to the NSData
if let toEncrypt = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
    // Create a cryptor instance
    var encryptedData = NSData()
    let cryptor = VSSCryptor()
    do {
        try cryptor.addPasswordRecipient(<# Password to encrypt data with #>, error: ())
        encryptedData = try cryptor.encryptData(toEncrypt, embedContentInfo: true, error: ())
    }
    catch let error as NSError {
        print("Error: \(error.localizedDescription)")
    }
}
//...

基于密码的解密

Objective-C
//...
// Assuming that we have received some password-based encrypted data.
// Assuming that we have some key pair generated earlier.
// Create a new VSSCryptor instance
VSSCryptor *decryptor = [[VSSCryptor alloc] init];
// Decrypt data
NSError *error = nil;
NSData *plainData = [decryptor decryptData:<# NSData with encrypted data #> password:<# Password used for encryption #> error:&error];
if (error != nil) {
    NSLog(@"Error decrypting data: %@", [error localizedDescription]);
    return;
}
// Compose initial message from the plain decrypted data
NSString *initialMessage = [[NSString alloc] initWithData:plainData encoding:NSUTF8StringEncoding];
//...
Swift
//...
// Assuming that we have received some password-based encrypted data.
// Assuming that we have some key pair generated earlier.
// Create a new VSSCryptor instance
let decryptor = VSSCryptor()
// Decrypt data
do {
    let plainData = try decryptor.decryptData(NSData(), password: "", error: ())
    // Compose initial message from the plain decrypted data
    if let initialMessage = NSString(data: plainData, encoding: NSUTF8StringEncoding) {
        // Use initialMessage.
        //...
    }
}
catch let error as NSError {
    print("Error: \(error.localizedDescription)")
}
//...

组合并验证签名

VSSSigner实例允许使用给定的私钥对某些数据进行签名。这可以用来确保某些消息/数据确实是由私钥的持有者生成并发送的。

组合签名

Objective-C
//...
// Assuming that we have some initial string message that we want to sign.
NSString *message = @"This is a secret message which should be signed.";
// Convert it to the NSData
NSData *toSign = [message dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO];
// Assuming that we have some key pair generated earlier.
// Create a new VSSSigner instance
VSSSigner *signer = [[VSSSigner alloc] init];
// Sign the initial data
NSError *error = nil;
NSData *signature = [signer signData:toSign privateKey:<# keyPair.privateKey #> keyPassword:<# Private key password or nil #> error:&error];
if (error != nil) {
    NSLog(@"Error composing a signature: %@", [error localizedDescription]);
    return;
}
// Use the signature.
//...
Swift
//...
// Assuming that we have some initial string message.
let message = NSString(string: "This is a secret message which should be signed.")
// Convert it to the NSData
if let toSign = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
    // Create the signer
    let signer = VSSSigner()
    // Compose the signature
    do {
        let signature = try signer.signData(toSign, privateKey: <# keyPair.privateKey() #>, keyPassword: <# Private key password or nil #>, error: ())
        // Use the signature.
        //...
    }
    catch let error as NSError {
        print("Error composing a signature: \(error.localizedDescription)")
    }
}
//...

验证签名

要验证某些签名,需要拥有我们想要验证签名的用户的公钥。

Objective-C
//...
// Assuming that we have the public key of a person whose signature we need to verify
// Assuming that we have a NSData object with signed data.
// Assuming that we have a NSData object with a signature.
// Create a new VSSSigner instance
VSSSigner *verifier = [[VSSSigner alloc] init];
// Verify the signature.
NSError *error = nil;
if (![verifier verifySignature:<# NSData containing the signature #> data:<# NSData used to compose the signature #> publicKey:<# keyPair.publicKey #> error:&error]) {
    NSLog(@"Error signature verification: %@", [error localizedDescription]);
    return;
}
// Signature seems OK.
//...
Swift
//...
// Assuming that we have the public key of a person whose signature we need to verify
// Assuming that we have a NSData object with signed data.
// Assuming that we have a NSData object with a signature.
// Create a new VSSSigner instance
let verifier = VSSSigner()
// Verify the signature.
do {
    try verifier.verifySignature(<# NSData containing the signature #>, data: <# NSData used to compose the signature #>, publicKey: <# keyPair.publicKey() #>, error: ())
    // Signature seems OK.
    //...
}
catch let error as NSError {
    print("Error signature verification: \(error.localizedDescription)")
}
//...

从密码中派生密钥

这项功能允许基于给定的初始参数生成字节序列,以确保相同的参数产生相同的字节序列。当应用程序不希望以明文形式使用某些敏感数据时(例如在会话之间保存密码或操作其他用户数据,例如电子邮件、电话号码等),这可能会很有用。在这种情况下,应用程序可以基于密码、电子邮件地址或其他任何明文数据生成安全的序列,这样这些数据将不会被泄露。使用生成的字节序列恢复初始明文数据是不可能的(或者至少在合理的时间内是不可能的)。以下是一些示例。

Objective-C
//...
// Assuming that we have some password which the application does not to expose in plain form.
NSString *password = <# NSString: user password in plain form#>;
// Create a new VSSPBKDF instance
// Salt parameter should contain the random sequence of bytes. In general, salt is public information. 
// If salt parameter is nil then VSSPBKDF will generate random salt automatically.
// If it is necessary to generate the same data later based on the user's input of the password
// it is recommended to generate salt data and store it for further use in VSSPBKDF instance creations:
NSData *salt = [VSSPBKDF randomBytesOfSize:<#size_t: size of the salt in bytes or 0 #>];       
// Iterations parameter should contain number of iterations for derivation function.
// If iterations == 0 then VSSPBKDF will use default number of iterations.
VSSPBKDF *pbkdf = [[VSSPBKDF alloc] initWithSalt:<#NSData: salt or nil for default new salt generation#> iterations:<#unsigned int: iterations count or 0 for default count #>];
NSError *error = nil;
// Derive secure sequence of bytes with required size based on the plain password.
NSData *data = [pbkdf keyFromPassword:password size:<# size_t: Desired length in bytes of the output data sequence #> error:&error];
if (error != nil) {
    NSLog(@"Error: %@", [error localizedDescription]);
    return;
} 
// Use the data instead of plain password.
//...
Swift
//...
// Assuming that we have some password which the application does not to expose in plain form.
let password = <# String: user password in plain form#>;
// Create a new VSSPBKDF instance
// Salt parameter should contain the random sequence of bytes. In general, salt is public information. 
// If salt parameter is nil then VSSPBKDF will generate random salt automatically.
// If it is necessary to generate the same data later based on the user's input of the password
// it is recommended to generate salt data and store it for further use in VSSPBKDF instance creations:
let salt = VSSPBKDF.randomBytesOfSize(<#size_t: size of the salt in bytes or 0 #>)       
// Iterations parameter should contain number of iterations for derivation function.
// If iterations == 0 then VSSPBKDF will use default number of iterations.
let pbkdf = VSSPBKDF(salt:<# NSData: salt or nil for default new salt generation #>, iterations: <#unsigned int: iterations count or 0 for default count #>)
do {
    // Derive secure sequence of bytes with required size based on the plain password.
    let data = try pbkdf.keyFromPassword(password, size: <# size_t: Desired length in bytes of the output data sequence #>)
    // Use the data instead of plain password.
}
catch (let error as NSError) {
    print("Error: \(error.localizedDescription)")
    return
}
//...

许可协议

使用受BSD 3-Clause License协议规范。有关详细内容,请参阅LICENSE文件。

参考