Skip to content

Commit

Permalink
Merge pull request #4 from internxt/add-hashing-native-methods
Browse files Browse the repository at this point in the history
[_]: Add sha256 and sha512 native hash methods for iOS
  • Loading branch information
PixoDev authored Jul 3, 2022
2 parents d96edae + e8e05c3 commit cf842c8
Show file tree
Hide file tree
Showing 13 changed files with 276 additions and 109 deletions.
4 changes: 0 additions & 4 deletions ios/Ciphers/AesCipher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ class AesCipher {
// Encrypts an input stream to an output stream given a key and an IV
// using AES256 CTR mode with No padding
public func encrypt(input: InputStream, output:OutputStream, key: [UInt8], iv: [UInt8] ,callback: (_:RnCryptoError?, _: Status?) -> Void ) -> Void {
do {
let algorithm = StreamCryptor.Algorithm.aes


Expand Down Expand Up @@ -71,9 +70,6 @@ class AesCipher {
output.close();

callback(nil,status)
} catch let error {
callback(RnCryptoError.encryptionFailed,Status.decodeError)
}


}
Expand Down
23 changes: 23 additions & 0 deletions ios/Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Extensions.swift
// RnCrypto
//
// Created by Robert on 1/7/22.
// Copyright © 2022 Facebook. All rights reserved.
//

import Foundation


// Data extensions
extension Data {
struct HexEncodingOptions: OptionSet {
let rawValue: Int
static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
}

func hexEncodedString(options: HexEncodingOptions = []) -> String {
let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
return self.map { String(format: format, $0) }.joined()
}
}
35 changes: 35 additions & 0 deletions ios/HMAC.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Hashes.swift
// RnCrypto
//
// Created by Robert on 28/6/22.
// Copyright © 2022 Facebook. All rights reserved.
//

import Foundation
import IDZSwiftCommonCrypto


enum HashInput {
case message ([UInt8])
case messages (Array<[UInt8]>)
}
class RnCryptoHMAC {
func sha256(inputs: Array<[UInt8]> ) -> [UInt8] {
return toAlgorithm(inputs: inputs, algorithm: HMAC.Algorithm.sha256)
}

func sha512(inputs: Array<[UInt8]>) -> [UInt8] {
return toAlgorithm(inputs: inputs, algorithm: HMAC.Algorithm.sha512)
}

private func toAlgorithm(inputs: Array<[UInt8]>, algorithm: HMAC.Algorithm) -> [UInt8] {
let hash = HMAC(algorithm: algorithm, key: inputs[0])
for (index, message) in inputs.enumerated() {
if index > 0 {
_ = hash.update(message)
}
}
return hash.final()
}
}
15 changes: 15 additions & 0 deletions ios/KeyDerivation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// KeyDerivation.swift
// RnCrypto
//
// Created by Robert on 1/7/22.
// Copyright © 2022 Facebook. All rights reserved.
//

import Foundation
import IDZSwiftCommonCrypto
class RnCryptoKeyDerivation {
func pbkdf2(password: String, salt: String, rounds: Int, derivedKeyLength: Int) -> [UInt8] {
return PBKDF.deriveKey(password: password, salt: salt, prf: PBKDF.PseudoRandomAlgorithm.sha512, rounds: uint(rounds), derivedKeyLength: UInt(derivedKeyLength))
}
}
44 changes: 19 additions & 25 deletions ios/Operations/DecryptFileOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,26 @@ class DecryptFileOperation : Operation {

override func main() {

do {
if self.plainFileStream == nil {
return self.callback(RnCryptoError.plainFile)
}

if self.encryptedFileStream == nil {
return self.callback(RnCryptoError.decryptedFile)
}

let iv = self.utils.hexStringToBytes(self.hexIv)
let key = self.utils.hexStringToBytes(self.hexKey)

self.aes.decrypt(
input: self.encryptedFileStream!,
output:self.plainFileStream!,
key: key,
iv: iv,
callback: {(error, status) in
self.callback(error)
}
)

} catch let error {
print("Error decrypting file", error);
self.callback(error)
if self.plainFileStream == nil {
return self.callback(RnCryptoError.plainFile)
}

if self.encryptedFileStream == nil {
return self.callback(RnCryptoError.decryptedFile)
}

let iv = self.utils.hexStringToBytes(self.hexIv)
let key = self.utils.hexStringToBytes(self.hexKey)

self.aes.decrypt(
input: self.encryptedFileStream!,
output:self.plainFileStream!,
key: key,
iv: iv,
callback: {(error, status) in
self.callback(error)
}
)

}
}
48 changes: 22 additions & 26 deletions ios/Operations/EncryptFileOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,29 @@ class EncryptFileOperation : Operation {

override func main() {

do {

if self.plainFileStream == nil {
return self.callback(RnCryptoError.plainFile)
}

if self.encryptedFileStream == nil {
return self.callback(RnCryptoError.encryptedFile)
}

let iv = self.utils.hexStringToBytes(self.hexIv)
let key = self.utils.hexStringToBytes(self.hexKey)


self.aes.encrypt(
input: self.plainFileStream!,
output: self.encryptedFileStream!,
key: key,
iv: iv,
callback: {(error, status) in
self.callback(error)
}
)
} catch let error {
print("Error encrypting file", error);
self.callback(error)

if self.plainFileStream == nil {
return self.callback(RnCryptoError.plainFile)
}

if self.encryptedFileStream == nil {
return self.callback(RnCryptoError.encryptedFile)
}

let iv = self.utils.hexStringToBytes(self.hexIv)
let key = self.utils.hexStringToBytes(self.hexKey)


self.aes.encrypt(
input: self.plainFileStream!,
output: self.encryptedFileStream!,
key: key,
iv: iv,
callback: {(error, status) in
self.callback(error)
}
)

}

}
15 changes: 14 additions & 1 deletion ios/RnCrypto.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,23 @@ @interface RCT_EXTERN_MODULE(RnCrypto, NSObject)
callback:(RCTResponseSenderBlock)callback)

RCT_EXTERN_METHOD(decryptFile:
(NSString*)encryptedFilePath
(NSString *)encryptedFilePath
plainFilePath:(NSString*)plainFilePath
hexKey:(NSString*)hexKey
hexIv:(NSString*)hexIv
callback:(RCTResponseSenderBlock)callback)

RCT_EXTERN_METHOD(sha512:
(NSArray*)inputs
resolver:(RCTPromiseResolveBlock)resolve)

RCT_EXTERN_METHOD(sha256:
(NSArray*)inputs
resolver:(RCTPromiseResolveBlock)resolve)


+ (BOOL)requiresMainQueueSetup
{
return NO;
}
@end
39 changes: 36 additions & 3 deletions ios/RnCrypto.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,46 @@ import IDZSwiftCommonCrypto
class RnCrypto: NSObject {
var encryptionQueue = OperationQueue()
var decryptionQueue = OperationQueue()
var utils = RnCryptoUtils()
var HMAC = RnCryptoHMAC()


func load() {
encryptionQueue.name = "EncryptionQueue"
decryptionQueue.name = "DecryptionQueue"
}


@objc func sha256(
_ inputs: NSArray,
resolve: RCTPromiseResolveBlock
) {
let byteInputs = inputs.map {
guard let input = $0 as? String else {return []}

return utils.hexStringToBytes(input)
} as Array<[UInt8]>

let result = HMAC.sha256(inputs: byteInputs)

return resolve(result.description.hex)
}

@objc func sha512(
_ inputs: NSArray,
resolve: RCTPromiseResolveBlock
) {
let byteInputs = inputs.map {
guard let input = $0 as Any as? String else {
return []
}
return utils.hexStringToBytes(input)
} as Array<[UInt8]>

let result = HMAC.sha512(inputs: byteInputs)

return resolve(result.description.hex)
}

@objc func encryptFile(
_ plainFilePath: String,
encryptedFilePath: String,
Expand All @@ -30,7 +63,7 @@ class RnCrypto: NSObject {
hexIv: hexIv,
callback: {(error: Error?) in
if error != nil {
callback([error, NSNull()])
callback([error!, NSNull()])
} else {
callback([NSNull(), NSNull()])
}
Expand Down Expand Up @@ -58,7 +91,7 @@ class RnCrypto: NSObject {
hexIv: hexIv,
callback: {(error: Error?) in
if error != nil {
callback([error?.localizedDescription, NSNull()])
callback([error?.localizedDescription ?? "Unknown error", NSNull()])
} else {
callback([NSNull(), NSNull()])
}
Expand Down
Loading

0 comments on commit cf842c8

Please sign in to comment.