Blackberry smartcard reader example - blackberry

I am writing an app for BlackBerry that utilizes a BlackBerry smartcard reader. There is not much documentation on the subject, so I'd really like if someone could give me starting examples.
Basically, there is one RSA private key on the card plus a certificate (for paired public key). I would like to be able to encrypt/decrypt data and also sign it as well. The final goal would be to establish an mutual-authenticated SSL connection using client certificate contained on the smartcard.
Here is the code I managed to come up with so far:
SmartCardReader btReader = null;
SmartCardReader[] readers = SmartCardReaderFactory.getInstalledReaders();
for (int i = 0; i < readers.length; i++) {
SmartCardReader reader = readers[i];
if (reader.getType().equalsIgnoreCase("bluetooth")) {
btReader = reader;
break;
}
}
SmartCardReaderSession readerSession = reader.openSession();
CryptoSmartCard card = (CryptoSmartCard) readerSession.getSmartCard();
RSACryptoToken token = (RSACryptoToken) card.getCryptoToken("RSA");
This token looks promising - has some nice methods, but with "cryptic" arguments. What to do next?

I think this is what you are looking for:
http://code.google.com/p/seek-for-android/wiki/BTPCSC

You have to implement SmartCardSession methods, also implement RSACryptoToken methods.
With SmartCardSession methods you will be able to communicate with smart card, and with RSACryptoToken methods, you will be able to perform crypto operations.
You have to read also about APDU protocol.

Related

Apple, iOS 13, CryptoKit, Secure Enclave - Enforce biometric authentication ahead of private key usage

I am working with Apple's new cryptokit library and am trying to get a basic use case to work.
Goal: I would like to create a private key in the secure enclave via the cryptokit, store the key's reference in the iOS device's key chain and ensure that the key can only be reinitialized in the secure enclave after the user has authenticated himself via some biometric authentication method.
Current state: So far, I am able to initialize a private key in the secure enclave via the following code:
var privateKeyReference = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init();
Furthermore, I can store and retrieve the corresponding private key's reference from the key chain. After retrieving the reference, I can reinitialize the private key in the secure enclave with the following code:
var privateKeyReference = getPrivateKeyReferenceFromKeyChain();
var privateKey = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init(
dataRepresentation: privateKeyReference
);
So far everything works as expected and all cryptographic operations with the private key succeed.
Now, as far as I understand the spare documentation by Apple, I should be able to modify the first initialization of the private key to something as follows.
let authContext = LAContext();
let accessCtrl = SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccesibleWhenUnlockedThisDeviceOnly,
[.privateKeyUsage, .userPresence, .biometryCurrentSet],
nil
);
var privateKeyReference = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init(
accessControl: accessCtrl!,
authenticationContext: authContext
);
Thereby, ensuring that the private key can only be reinitialized, when the user authenticates himself via some biometric authentication method. The initial initialization stil works without any errors.
Problem: However, adding the previous code, I do not get any biometric authentication prompt and can not use the private key at all after reinitialization. The following error is logged whenever I try to execute some cryptographic operation with the reinitialized key, here for example some signing:
Error Domain=CryptoTokenKit Code=-9 "setoken: unable to sign digest" UserInfo={NSLocalizedDescription=setoken: unable to sign digest})
As far as I could guess from here, I think that Code=-9 refers to the "authenticationNeeded" error.
Question: Can someone point me to some documentation or tutorial how to achieve what I am looking for or explain to me what I am missing?
Thanks!
Cross-Post: https://forums.developer.apple.com/message/387746
After a couple of days of patience I was able to obtain an answer from the Apple development support. They suggested the following method which only differs a little bit from my approach:
var error: Unmanaged<CFError>? = nil;
let accessCtrl = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccesibleAfterFirstUnlockThisDeviceOnly,
[.privateKeyUsage, .biometryCurrentSet],
&error
);
var privateKeyReference = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init(
accessControl: accessCtrl
);
Additionally, in the meantime iOS version 13.1.3 was released and, after upgrading my device, the above code started working. So either there is a subtle difference between mine and Apple's code or it is related to the update. Nevertheless, it is working now.

How can I add Amount using Cyber source SDK iOS?

I downloaded Cyber Source SDK iOS from Github. It is also working fine. But I need to set total amount and I can not find any parameter in SDK. How to set amount in Cyber source using SDK?
I don't know it is set by SDK or Backend(API). Please check my code below:
//Card data
let cardData = InAppSDKCardData.init()
cardData.accountNumber = txtCardNumber.text
cardData.expirationMonth = txtMonth.text
cardData.expirationYear = txtYear.text
cardData.cvNumber = txtCVV.text
//Create Transaction object
let transactionObj = InAppSDKTransactionObject.init()
transactionObj.billTo = getBillToData()
transactionObj.cardData = cardData
//Get the Merchant data and credentials and assign.
transactionObj.merchant = getMerchantData()
//Set the End point / Environment. Test or Live
InAppSDKSettings.sharedInstance()?.inAppSDKEnvironment = INAPPSDK_ENV_TEST
//Enable log for debugging
InAppSDKSettings.sharedInstance()?.enableLog = true
//Obtain the gateway sharted instance.
let gatWay = InAppSDKGateway.sharedInstance()
result = (gatWay?.performPaymentDataEncryption(transactionObj, with: self))!
if (result) {
NSLog("InAppSDK: Request Accepted. Expect the response in the delegate method.");
}
else {
NSLog("InAppSDK: Request NOT Accepted. Verify the input values if any one is invalid.");
}
And I got a response like this
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-1623853623"><wsu:Created>2019-08-01T10:25:43.747Z</wsu:Created></wsu:Timestamp></wsse:Security></soap:Header><soap:Body><c:replyMessage xmlns:c="urn:schemas-cybersource-com:transaction-data-1.120"><c:merchantReferenceCode>Cyber_iOS</c:merchantReferenceCode><c:requestID>5646551432976553503004</c:requestID><c:decision>ACCEPT</c:decision><c:reasonCode>100</c:reasonCode><c:requestToken>AhizbwSTMhmkg5ScYGkcEQFRp++q/94CP9hk0ky9GK+AnABMoAny</c:requestToken><c:encryptedPayment><c:data>eyJkYXRhIjoiK1ZrdmNpTDhpcStyeEt2RytTMDl3R05MbTFGZzlRcXZpQUE3K3FWOFNvckJqYnp1b0lcL3VzRUs0RWpDZkpxZ1pJejJRbWd3cjBNdGxpVXltS2k0bERNS3lFZmdHZmlOS1wvOWRIMWpMXC9WaCszbk5nOXV6NVp2eG54OVpJbmExNkpBbmtvMmt0OSs0S2lDdW1TYkVBVlVtSkdrRm12ZFhqYlBRUXFzVXNcL0xjS2tlVEkzb1RrSkhFXC9jWVBkRXRHZUs1bVErOW8zbDUySWtUb0xPWkJJcUxmeEtcLzNiNUVRY3FcL2ZZOXZJT3l1aFVnZEc2OXVwXC9oQTJJakpORmY1bm1ZcmQ1bkRkVEdEa1EyeGY3RnNGTDdKRjYxdlNUbHljcHIweHFvS09adDNpQVplM1wvR3htT2p1Unp6XC9oTFhsOTZNRFFaUUc1eXZHZHBXaUNydEhRPT0iLCJoZWFkZXIiOnsiYXBwbGljYXRpb25EYXRhIjoiNDc3NTY5NjQzRDMwMzYzMzYxNjI2MTYzMzYyRDYxMzEzMDMzMkQzNDY2NjY2NTJEMzgzOTYzMzAyRDM4MzczNDY2MzMzNTM1NjI2NTMxNjM2MzNCNDQ2MTc0NjU1NDY5NkQ2NTNEMzIzMDMxMzkyRDMwMzgyRDMwMzE1NDMxMzAzQTMyMzUzQTM0MzMyRTM2MzAzOTM1MzAzNTM4NUEiLCJlcGhlbWVyYWxQdWJsaWNLZXkiOiJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVaRE41dU8rb1R0eXNzdlwvb1V2SjZhQnE1bkVrWVBXZEdDT01sb1YyYkJpaHVROTlHSnBobEk2elwvOHg2M1dmUGpjbGFTcG04ODBJZGNaU0czUkRnNVpRPT0iLCJwdWJsaWNLZXlIYXNoIjoieXRLSjgwc3JjWXppQnVwNzRcL0R5K3RTV1FQSENwXC9ZbkFabGhcL3lXOFk3ND0iLCJ0cmFuc2FjdGlvbklkIjoiNTY0NjU1MTQzMjk3NjU1MzUwMzAwNCJ9LCJzaWduYXR1cmVBbGdJbmZvIjoiU0hBMjU2Iiwic2lnbmF0dXJlIjoiNXdya1BuTEtJZWoxV0ZEVjVZNUJEc0orTUg2QkJSN2Zoa2FVM1ZsQzE2OD0iLCJ2ZXJzaW9uIjoiMS4xLjEuMiJ9</c:data></c:encryptedPayment><c:encryptPaymentDataReply><c:reasonCode>100</c:reasonCode><c:requestDateTime>2019-08-01T10:25:43Z</c:requestDateTime></c:encryptPaymentDataReply><c:reserved><ics_message xmlns="urn:schemas-cybersource-com:transaction-data:ics"><encrypt_payment_data_rcode>1</encrypt_payment_data_rcode><ics_return_code>1000000</ics_return_code><encrypt_payment_data_rmsg>Request was processed successfully.</encrypt_payment_data_rmsg><ics_rcode>1</ics_rcode><encrypt_payment_data_return_code>1001000</encrypt_payment_data_return_code><ics_rmsg>Request was processed successfully.</ics_rmsg><request_id>5646551432976553503004</request_id><encrypt_payment_data.reason_code>100</encrypt_payment_data.reason_code><encrypt_payment_data_rflag>SOK</encrypt_payment_data_rflag><request_token>AhizbwSTMhmkg5ScYGkcEQFRp++q/94CP9hk0ky9GK+AnABMoAny</request_token><ics_decision_reason_code>100</ics_decision_reason_code><encrypt_payment_data_request_date_time>2019-08-01T102543Z</encrypt_payment_data_request_date_time><ics_rflag>SOK</ics_rflag><merchant_ref_number>Cyber_iOS</merchant_ref_number><encrypted_payment_data>eyJkYXRhIjoiK1ZrdmNpTDhpcStyeEt2RytTMDl3R05MbTFGZzlRcXZpQUE3K3FWOFNvckJqYnp1b0lcL3VzRUs0RWpDZkpxZ1pJejJRbWd3cjBNdGxpVXltS2k0bERNS3lFZmdHZmlOS1wvOWRIMWpMXC9WaCszbk5nOXV6NVp2eG54OVpJbmExNkpBbmtvMmt0OSs0S2lDdW1TYkVBVlVtSkdrRm12ZFhqYlBRUXFzVXNcL0xjS2tlVEkzb1RrSkhFXC9jWVBkRXRHZUs1bVErOW8zbDUySWtUb0xPWkJJcUxmeEtcLzNiNUVRY3FcL2ZZOXZJT3l1aFVnZEc2OXVwXC9oQTJJakpORmY1bm1ZcmQ1bkRkVEdEa1EyeGY3RnNGTDdKRjYxdlNUbHljcHIweHFvS09adDNpQVplM1wvR3htT2p1Unp6XC9oTFhsOTZNRFFaUUc1eXZHZHBXaUNydEhRPT0iLCJoZWFkZXIiOnsiYXBwbGljYXRpb25EYXRhIjoiNDc3NTY5NjQzRDMwMzYzMzYxNjI2MTYzMzYyRDYxMzEzMDMzMkQzNDY2NjY2NTJEMzgzOTYzMzAyRDM4MzczNDY2MzMzNTM1NjI2NTMxNjM2MzNCNDQ2MTc0NjU1NDY5NkQ2NTNEMzIzMDMxMzkyRDMwMzgyRDMwMzE1NDMxMzAzQTMyMzUzQTM0MzMyRTM2MzAzOTM1MzAzNTM4NUEiLCJlcGhlbWVyYWxQdWJsaWNLZXkiOiJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVaRE41dU8rb1R0eXNzdlwvb1V2SjZhQnE1bkVrWVBXZEdDT01sb1YyYkJpaHVROTlHSnBobEk2elwvOHg2M1dmUGpjbGFTcG04ODBJZGNaU0czUkRnNVpRPT0iLCJwdWJsaWNLZXlIYXNoIjoieXRLSjgwc3JjWXppQnVwNzRcL0R5K3RTV1FQSENwXC9ZbkFabGhcL3lXOFk3ND0iLCJ0cmFuc2FjdGlvbklkIjoiNTY0NjU1MTQzMjk3NjU1MzUwMzAwNCJ9LCJzaWduYXR1cmVBbGdJbmZvIjoiU0hBMjU2Iiwic2lnbmF0dXJlIjoiNXdya1BuTEtJZWoxV0ZEVjVZNUJEc0orTUg2QkJSN2Zoa2FVM1ZsQzE2OD0iLCJ2ZXJzaW9uIjoiMS4xLjEuMiJ9</encrypted_payment_data></ics_message></c:reserved></c:replyMessage></soap:Body></soap:Envelope>
Thanks in advance.
This SDK is intended for one purpose - to reduce PCI scope by encrypting the card data which can then be passed to your server. Since it is only encrypting the card data there is no need for an amount.
Once you have the encrypted data you pass that to your server and can then use it to authorize the card. See "Using the Payment Blob" on this page https://github.com/CyberSource/cybersource-ios-sdk. This is the point where you will need the amount. You will also have to pass the amount to your server if it is coming from your iOS App.

AWS AppSync multiple subscriptions in same view controller not working - iOS Swift

Just FYI I posted this question originally in the AWS AppSync forum (in case in the future AWS answers it).
I have been trying to make a simple Posts app like the one in the docs but I have found no documentation or guides that handle multiple subscriptions in one view controller.
Three mutations: onCreatePost, onUpdatePost, onDeletePost
(and of course three subscriptions to those mutations)
In Xcode, I have three functions called during viewDidLoad(): subscribeToNewPosts(), subscribeToUpdatedPosts(), subscribeToDeletedPosts()
Each subscription function works and creates a subscription with the correct functionality and updates the table view accordingly if used alone. But, if called one after the other, only the last subscription will actually receive data and update the table view. I put a breakpoint to check out topicSubscribersDictionary in AppSyncMQTTClient.swift after subscribing to all three mutations
func startNewSubscription(subscriptionInfo: AWSSubscriptionInfo) {
var topicQueue = [String]()
let mqttClient = MQTTClient<AnyObject, AnyObject>()
mqttClient.clientDelegate = self
for topic in subscriptionInfo.topics {
if topicSubscribersDictionary[topic] != nil {
// if the client wants subscriptions and is allowed we add it to list of subscribe
topicQueue.append(topic)
}
}
mqttClients.append(mqttClient)
mqttClientsWithTopics[mqttClient] = topicQueue
mqttClient.connect(withClientId: subscriptionInfo.clientId, toHost: subscriptionInfo.url, statusCallback: nil)
}
and all three subscriptions are in fact in the dictionary...
Do I need multiple instances of appSyncClient, one for each subscription? Is it a problem with the schema design?
schema.graphql
schema.json
mutations.graphql
queries.graphql
subscriptions.graphql
Example use case: simple chat app. New conversation started = OnCreatePostSubscription; new incoming message in that conversation = OnUpdatePostSubscription
Are you using API Key for authorization in AppSync? If you are using API Key only one subscription is supported by the SDK at this point. Could you switch to IAM (Cognito Identity) or Cognito UserPools based auth and see if multiple subscriptions work for you?
I managed to have several subscriptions working with API Key by replacing the call startSubscriptions to startNewSubscription inside AWSAppSyncSubscriptionWatcher
if let subscriptionInfo = subscriptionResult.subscrptionInfo {
self.subscriptionTopic = subscriptionResult.newTopics
self.client?.addWatcher(watcher: self, topics: subscriptionResult.newTopics!, identifier: self.uniqueIdentifier)
//self.client?.startSubscriptions(subscriptionInfo: subscriptionInfo)
subscriptionInfo.forEach { self.client?.startNewSubscription(subscriptionInfo: $0) }
}
Couldn't find any side effect with this approach yet, apart from requiring to fork the iOS SKD

Cannot set PubNub auth key Swift iOS

I have a webapp and the iOS app built in Swift. The thing is I don't know Swift and I'm trying to modify the iOS app in order to add the authorization key to the PubNub client before subscribing/publishing to channels.
Link to PubNub docs
PRE:
Access Manager is enabled
my_auth_key is hardcoded and already enabled form the server for the corresponding channel I want to subscribe.
Here is the code
What's the correct way to set the auth key?
Thanks in advance
Polak, mentioned docs code snippet refer to previously created instance to get it's pre-configured PNConfiguration instance and change required field. This practice can be used in case if you need change something at run-time.
If you have data for authKey at the moment of client initialization, you can set it:
var pubnubClient: PubNub = {
let configuration = PNConfiguration(publishKey: UCConstants.PubNub.publishKey, subscribeKey: UCConstants.PubNub.subscribeKey)
configuration.authKey = "my_auth_key"
return PubNub.clientWithConfiguration(configuration)
}()
Also, I've tried exact your code and don't have any issues with setting of authKey, because I can see it with subscribe request.
If you still will have troubles with PAM and auth key usage, please contact us on support#pubnub.com
Looks like you can:
let configuration = PNConfiguration(
authKey: "super_secret",
publishKey: UCConstants.PubNub.publishKey,
subscribeKey: UCConstants.PubNub.subscribeKey
)
Based on the Obj-C code: https://github.com/pubnub/objective-c/blob/8c1f0876b5b34176f33681d22844e8d763019635/PubNub/Data/PNConfiguration.m#L174-L181

Communicating between (chat) server and client

just to clarify certain questions.
Let's say I'm making a chat application. Most of the online tutorials are basic server-client programs that send the chat message directly as strings.
So what if there is someone that came online, or offline. How would the client notify the server of such changes? What I came up with is to use flags {online}User, {offline}user, {privatechat}blabla.
What if someone knew how your code and that would allow them to sabotage by keep sending {online}blabla.
This would work, but has some flaws that I could think of as well. What would be the correct or better way to do this?
Can someone point me in the right direction? Thanks.
Or another example, in games. To tell the unit to move right, does it send a string back to the server {unit}{move right}? Something along those lines.
I kinda got the logic on how to make the chat server. If I just prefix a "{chat}" to the textbox. As long as I read this command "{chat}" I'll just ignore whichever commands which comes along.
How about in an RTS (not that I'm gonna make one, just curious), you mean there's literally 50 over strings telling how units move, attack, take damage, actions etc? Will all these commands be done on one thread? or multi-threaded?
Well you have to implement session-handling and send sessionToken with your order to move a unit in game. So server will be able to check whether pointed user have rights to order the pointed unit etc. Same things with chats.
In my chat, every client sends some PING message to server every two minutes. So if 5 minutes passed and no PING is received, server counts the user as [offline].
If you are afraid of cheating users who reverse engineer your client and can make serious troubles to the system with cheats, you have to do two things:
make server to check if given
user order is valid
implement bot-detection. check if
user makes some actions with some
constant time interval or if user
uses some limited amount of words in
chat etc.
I hope this post at least gives you some point.
The example of server logic is following:
[WebMethod]
string LoginUser(string login, string pwd)
{
if( dal.IsCorrectUser(login,pwd) )
{
string token = dal.MakeSession(login);
return string;
}
return "-1";
}
[WebMethod]
bool UserOrder(string token, string order)
{
if( !dal.SessionExist(token) )
{
return false;
}
int userId = dal.GetUserBySession(token);
if(! dal.ValidOrderForUser(userId,order) )
{
dal.RegisterWrongOrder(userid,order); // For cheaters-detecting purposes
return false;
}
return dal.ExecuteUserOrder(userId, order);
}
In fact you can send string or any serializable objects as an user-order.
[Serializable]
struct UserOrder
{
int unitId;
int Order;
}
All samples are for c#. Just to demonstrate logic.

Resources