Creating a low-s ECDSA signature in iOS - ios

I need to interact with Hyperledger Fabric in an iOS application, and I've run into a problem when creating the proposal signature. Fabric requires low-s ECDSA, but I can't find a way to specify that in Apple's crypto functions. Without specifying low-s, my calls fail about %50 of the time, when S is higher than R.
My signing code is pretty simple:
static func sign(data:Data, withPrivateKey:SecKey) throws -> Data {
var error: Unmanaged<CFError>?
guard
let signature = SecKeyCreateSignature(
withPrivateKey,
.ecdsaSignatureMessageX962SHA256,
data as CFData,
&error
) as Data?
else {
throw error!.takeRetainedValue()
}
return signature
}

Related

Using AWS Amplify Auth with iOS Combine

I am trying to use AWS Amplify Auth with iOS Combine to integrate social network logins (Google, Facebook and Apple) but I blocked with:
func signInWithFacebook(context: Any) -> AnyPublisher<AuthSignInResult, AuthError> {
guard let window = context as? UIWindow else {
return Fail(error: AuthError(error: Foo.unexpectedError(reason: "empty context")))
.eraseToAnyPublisher()
}
return Amplify.Auth.signInWithWebUI(for: .facebook, presentationAnchor: window)
.resultPublisher
.eraseToAnyPublisher()
}
FooError is a basic enum
enum FooError: Error {
case unexpectedError(reason: String)
}
However, I cannot seem to get the Fail construct correct, I am getting the following error: 'AuthSignInStep' cannot be constructed because it has no accessible initializers
Thoughts on how I can construct the Fail mechanism?

How to access JSON response in Swift using AWS API Gateway-generated iOS SDK

I have a working REST API based on this API Gateway tutorial. I'm able to successfully invoke it via the test functionality of the AWS Console; and I'm able to successfully invoke it via my simple iOS Swift 4.2 Xcode application using the iPhone XR simulator.
I know it's working via a real, live external call because I can see the Cloudwatch logs which always register a 200 response and is sending the results back to the Client.
My problem is really in understanding the Swift code, and I'm hoping that a Swift expert can help me understand how to unpack result in the code below.
Here's my code in ViewController.swift for invoking the REST API and attempting to print result to the console:
#IBAction func userInvokeApi(_ sender: UIButton) {
print("You clicked invoke api...")
let client = SVTLambdaGateClient.default()
client.calcGet(operand2: "3", _operator: "+", operand1: "5").continueWith{ (task: AWSTask?) -> AnyObject? in
if let error = task?.error {
print("Error occurred: \(error)")
return nil
}
if let result = task?.result {
// Do something with result
print("The result is... \(result)")
}
return nil
}
}
As pointed out in the comments below, I'm getting the following result because it's printing out the address of the object:
You clicked invoke api...
The result is... <AmplifyRestApiTest.Empty: 0x600002020770> {
}
(where AmplifyRestApiTest is the name of my Xcode project.)
UPDATE When I set a breakpoint on the print statement, this is what I see in the Debug pane:
UPDATE 2
When I type task?.result there are two viable properties as per this answer from the Amplify team: error and result. So, since my API responds successfully I am assuming I just don't know how to view result.
Can someone help me understand what steps I must take to access members of this class object?
Here is the corresponding method in the API Gateway-generated iOS Swift SDK code:
/*
#param operand2
#param _operator
#param operand1
return type: Empty
*/
public func calcGet(operand2: String, _operator: String, operand1: String) -> AWSTask<Empty> {
let headerParameters = [
"Content-Type": "application/json",
"Accept": "application/json",
]
var queryParameters:[String:Any] = [:]
queryParameters["operand2"] = operand2
queryParameters["operator"] = _operator
queryParameters["operand1"] = operand1
let pathParameters:[String:Any] = [:]
return self.invokeHTTPRequest("GET", urlString: "/calc", pathParameters: pathParameters, queryParameters: queryParameters, headerParameters: headerParameters, body: nil, responseClass: Empty.self) as! AWSTask<Empty>
}
I'm fairly certain this return type of Empty refers to the Empty model defined for the REST API as shown in the screenshot below. I think it's "empty" because the API doesn't alter the response from the Lambda function back to the Client. So, it's all pass-through. Indeed, the tutorial explains that the other models -- Output and Result -- are not used because it "relies on the passthrough behavior and does not use this model."
Any thoughts?

What is the best practice to deal with RxSwift retry and error handling

I read some post says that the best practice to deal with RxSwift is to only pass fatal error to the onError and pass Result to the onNext.
It makes sense to me until I realise that I can't deal with retry anymore since it only happen on onError.
How do I deal with this issue?
Another question is, how do I handle global and local retry mixes together?
A example would be, the iOS receipt validation flow.
1, try to fetch receipt locally
2, if failed, ask Apple server for the latest receipt.
3, send the receipt to our backend to validate.
4, if success, then whole flow complete
5, if failed, check the error code if it's retryable, then go back to 1.
and in the new 1, it will force to ask for new receipt from apple server. then when it reaches 5 again, the whole flow will stop since this is the second attempt already. meaning only retry once.
So in this example, if using state machine and without using rx, I will end up using state machine and shares some global state like isSecondAttempt: Bool, shouldForceFetchReceipt: Bool, etc.
How do I design this flow in rx? with these global shared state designed in the flow.
I read some post says that the best practice to deal with RxSwift is to only pass fatal error to the onError and pass Result to the onNext.
I don't agree with that sentiment. It is basically saying that you should only use onError if the programmer made a mistake. You should use errors for un-happy paths or to abort a procedure. They are just like throwing except in an async way.
Here's your algorithm as an Rx chain.
enum ReceiptError: Error {
case noReceipt
case tooManyAttempts
}
struct Response {
// the server response info
}
func getReceiptResonse() -> Observable<Response> {
return fetchReceiptLocally()
.catchError { _ in askAppleForReceipt() }
.flatMapLatest { data in
sendReceiptToServer(data)
}
.retryWhen { error in
error
.scan(0) { attempts, error in
let max = 1
guard attempts < max else { throw ReceiptError.tooManyAttempts }
guard isRetryable(error) else { throw error }
return attempts + 1
}
}
}
Here are the support functions that the above uses:
func fetchReceiptLocally() -> Observable<Data> {
// return the local receipt data or call `onError`
}
func sendReceiptToServer(_ data: Data) -> Observable<Response> {
// send the receipt data or `onError` if the server failed to receive or process it correctly.
}
func isRetryable(_ error: Error) -> Bool {
// is this error the kind that can be retried?
}
func askAppleForReceipt() -> Observable<Data> {
return Observable.just(Bundle.main.appStoreReceiptURL)
.map { (url) -> URL in
guard let url = url else { throw ReceiptError.noReceipt }
return url
}
.observeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
.map { try Data(contentsOf: $0) }
}

Encrypt RSA/ECB/OAEPWithSHA-256AndMGF1Padding Swift

I am going to say in advance i don't know too much about cryptography (Basics only). I am trying to Implement a Credential OpenHome Service and I want to encrypt a password to send it to the device.
The device provides a function written in C that returns a public key String that looks like that:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzjFGuEKD0uWxzb47oRbiSP2uDwVJPeWU7m9VXi626V6lameTzdtwj2eYVZTIAsAW7yW4or2skn7oHqFG4GvhMzgMwoQjKFxeCPPFXRSotnt26AN1DhvFJp3V/d+MpmkzI07iWcD5eNe4EVNK9GSE4JOEHhJ/JYBVMiu04XE5aqwIDAQAB
The Android implementation has been already done and the specs given are
RSA/ECB/OAEPWithSHA-256AndMGF1Padding
also there is a web site that gives "instructions" when encrypting
http://wiki.openhome.org/wiki/Av:Developer:CredentialsService
I have tried so far these libraries:
SwiftyRSA, Heimdall, SwCrypt
I really thing that one of my main failures are I don't understand what I have, what do I need and finally how to achieve it using swift.
ideally at the end i will have a functions like
func encryptMessage(message:String, whithPublicKey key:String)->String
thank you very much.
After a long research i have just implemented my own solution rather than using libraries and not understanding what was going on. It is always good to know what happens and it this case it is not rocket science.
On iOS if you want to encrypt/decrypt you need to use a key stored on the keychain. If, in my case, i have been given the public key i can import it and also I can do the same with the private key. Please see my HelperClass Here.
Then, and from only from iOS 10, you can call this 2 methods for encrypting and decrypting
let error:UnsafeMutablePointer<Unmanaged<CFError>?>? = nil
let plainData = "A Plain text...".data(using: .utf8)
if let encryptedMessageData:Data = SecKeyCreateEncryptedData(publicSecKey, .rsaEncryptionOAEPSHA256, plainData! as CFData,error) as Data?{
print("We have an encrypted message")
let encryptedMessageSigned = encryptedMessageData.map { Int8(bitPattern: $0) }
print(encryptedMessageSigned)
if let decryptedMessage:Data = SecKeyCreateDecryptedData(privateSecKey, .rsaEncryptionOAEPSHA256, encryptedMessageData as CFData,error) as Data?{
print("We have an decrypted message \(String.init(data: decryptedMessage, encoding: .utf8)!)")
}
else{
print("Error decrypting")
}
}
else{
print("Error encrypting")
}
Also, if you want before iOS 10 you have the functions:
func SecKeyEncrypt(_ key: SecKey,
_ padding: SecPadding,
_ plainText: UnsafePointer<UInt8>,
_ plainTextLen: Int,
_ cipherText: UnsafeMutablePointer<UInt8>,
_ cipherTextLen: UnsafeMutablePointer<Int>) -> OSStatus
And
func SecKeyDecrypt(_ key: SecKey,
_ padding: SecPadding,
_ cipherText: UnsafePointer<UInt8>,
_ cipherTextLen: Int,
_ plainText: UnsafeMutablePointer<UInt8>,
_ plainTextLen: UnsafeMutablePointer<Int>) -> OSStatus
But these give less options and They are quite resticted.
Worth mentioning that my public and private key where generate on android using
public static String createStringFromPublicKey(Key key) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key.getEncoded());
return new String(Base64.encode(x509EncodedKeySpec.getEncoded(), Base64.NO_WRAP), "UTF-8");
}
and
public static String createStringFromPrivateKey(Key key) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key.getEncoded());
return new String(Base64.encode(pkcs8EncodedKeySpec.getEncoded(), Base64.NO_WRAP), "UTF-8");
}

I get memory leak when I execute CTFontManagerRegisterGraphicsFont

I am wondering why I am receiving memory leak in case when CTFontManagerRegisterGraphicsFont is called. Is it possible because it is debug build ? Or it is connected with wrong usage of the apple API?
public static func register(from url: URL) throws {
guard let fontDataProvider = CGDataProvider(url: url as CFURL) else {
throw RegisterFontError(errorMessage: "Could not create font data provider for \(url).")
}
let font = CGFont(fontDataProvider)
var error: Unmanaged<CFError>?
guard CTFontManagerRegisterGraphicsFont(font, &error) else {
throw error!.takeUnretainedValue()
}
}
Apple Instruments :
After investigation of the parameters of the CTFontManagerRegisterGraphicsFont I found that error parameter is type of UnsafeMutablePointer<Unmanaged<CFError>?>?. And the main issue is connected with Unmanaged type.
So what is Unmanaged type.
An Unmanaged wrapper, like an Optional wrapper, provides a layer of
safety between your code and a potentially nasty crash. The
Unmanaged type stores a pointer whose memory is not controlled by
the Swift runtime system. Before using this data, you take
responsibility for how this memory should stay alive.
And what is UnsafeMutablePointer
UnsafeMutablePointer provides no automated memory management or
alignment guarantees. You are responsible for handling the life cycle
of any memory you work with through unsafe pointers to avoid leaks or
undefined behavior.
So as it possible to understand we should fix my code with this few code lines.That will release error after we fetch error description.
public static func register(from url: URL) throws {
guard let fontDataProvider = CGDataProvider(url: url as CFURL) else {
throw RegisterFontError(errorMessage: "Could not create font data provider for \(url).")
}
let font = CGFont(fontDataProvider)
var error: Unmanaged<CFError>?
guard CTFontManagerRegisterGraphicsFont(font, &error) else {
let message = error.debugDescription
error?.release()
throw RegisterFontError.init(errorMessage: message)
}
}

Resources