Skip to content

Commit

Permalink
add encrypt decrypt func & change datatypes
Browse files Browse the repository at this point in the history
  • Loading branch information
hqjang-pepper committed Jul 7, 2023
1 parent df9e3c4 commit 95e41a8
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 103 deletions.
20 changes: 20 additions & 0 deletions Sources/TorusUtils/Convenience/SECP256k1.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@ public struct SECP256K1 {

extension SECP256K1 {
static let context = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY))

public static func ecdh(pubKey: secp256k1_pubkey, privateKey: Data) -> secp256k1_pubkey? {
var localPubkey = pubKey // Pointer takes a variable
if privateKey.count != 32 { return nil }
let result = privateKey.withUnsafeBytes { (a: UnsafeRawBufferPointer) -> Int32? in
if let pkRawPointer = a.baseAddress, let ctx = context, a.count > 0 {
let privateKeyPointer = pkRawPointer.assumingMemoryBound(to: UInt8.self)
let res = withUnsafeMutablePointer(to: &localPubkey) {
secp256k1_ec_pubkey_tweak_mul(ctx, $0, privateKeyPointer)
}
return res
} else {
return nil
}
}
guard let res = result, res != 0 else {
return nil
}
return localPubkey
}

public static func signForRecovery(hash: Data, privateKey: Data, useExtraEntropy: Bool = false) -> (serializedSignature: Data?, rawSignature: Data?) {
if hash.count != 32 || privateKey.count != 32 {
Expand Down
14 changes: 1 addition & 13 deletions Sources/TorusUtils/DataModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,6 @@ public struct NonceMetadataParams: Codable {
}
}

public enum BNString {
case string(String)
case bn(BigInt)

func toString() -> String? {
switch self {
case .string(let str):
return str
case .bn(let bigint):
return String(bigint)
}
}
}


typealias StringifiedType = [String: Any]
152 changes: 92 additions & 60 deletions Sources/TorusUtils/Extensions/TorusUtils+extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,19 +143,20 @@ extension TorusUtils {
var encShares: [Ecies] = []
var encErrors: [Error] = []

for (i, idx) in nodeIndexesBigInt.enumerated() {
for (i, _) in nodeIndexesBigInt.enumerated() {
let shareIdx = String(nodeIndexesBigInt[i], radix: 16).addLeading0sForLength64()
let share = shares[shareIdx]
let nodePubKey = "04" + nodePubKeys[i].X.addLeading0sForLength64() + nodePubKeys[i].Y.addLeading0sForLength64()

let shareData = share?.share
let shareString = String(shareData!, radix: 16)

if shareData == nil {
continue
}
do {
// TODO: we need encrypt logic here
let encShareData = try encryptData(publicKey: nodePubKey, msg: shareData!)
let encShareData = try encrypt(publicKey: nodePubKey, msg: shareString)
encShares.append(encShareData)
} catch {
encErrors.append(error)
Expand All @@ -172,7 +173,7 @@ extension TorusUtils {
pubKeyY: pubKeyY,
encryptedShare: encParamsMetadata.ciphertext!,
encryptedShareMetadata: encParamsMetadata,
nodeIndex: Int(shareJson!.shareIndex),
nodeIndex: BigUInt(shareJson!.shareIndex),
keyType: "secp256k1",
nonceData: nonceData,
nonceSignature: nonceParams.signature
Expand Down Expand Up @@ -965,90 +966,110 @@ extension TorusUtils {

func decryptNodeData(eciesData: EciesHex, ciphertextHex: String, privKey: Data) throws -> Data {
let metadata = encParamsHexToBuf(eciesData: eciesData.omitCiphertext())
let ciphertext = Data(hexString: ciphertextHex)!

let eciesOpts = Ecies(
iv: metadata.iv,
ephemPublicKey: metadata.ephemPublicKey,
ciphertext: ciphertext,
ciphertext: ciphertextHex,
mac: metadata.mac
)
let decryptedSigBuffer = try decryptOpts(privateKey: privKey, opts: eciesOpts)
return decryptedSigBuffer
let decryptedSigBuffer = try decrypt(privateKey: privKey, opts: eciesOpts)
return decryptedSigBuffer.data(using: .utf8)!
}

// MARK: decrypt opts
// TODO: check toHexString() is right way or not
public func decryptOpts(privateKey: Data, opts: Ecies, padding: Bool = false) throws -> Data {
let k = opts.ephemPublicKey.toHexString()
let ephermalPublicKey = k.strip04Prefix()
private func decrypt(privateKey: Data, opts: Ecies) throws -> String {
var result: String = ""
let ephermalPublicKey = opts.ephemPublicKey.strip04Prefix()
let ephermalPublicKeyBytes = ephermalPublicKey.hexa
var ephermOne = ephermalPublicKeyBytes.prefix(32)
var ephermTwo = ephermalPublicKeyBytes.suffix(32)
// Reverse because of C endian array storage
ephermOne.reverse(); ephermTwo.reverse()
ephermOne.append(contentsOf: ephermTwo)
let ephemPubKey = secp256k1_pubkey.init(data: array32toTuple(Array(ephermOne)))

let privKeyStr = privateKey.toHexString()

guard
// Calculate g^a^b, i.e., Shared Key
let data = Data(hexString: privateKey.toHexString()),
let secret = ecdh(pubKey: ephemPubKey, privateKey: data)
let data = Data(hexString: privKeyStr),
let sharedSecret = SECP256K1.ecdh(pubKey: ephemPubKey, privateKey: data)
else {
throw TorusUtilError.decryptionFailed
throw TorusUtilError.runtime("ECDH Error")
}

let secretData = secret.data
let secretPrefix = tupleToArray(secretData).prefix(32)
let reversedSecret = secretPrefix.reversed()

let iv = opts.iv.toHexString().hexa
let newXValue = reversedSecret.hexa
let sharedSecretData = sharedSecret.data
let sharedSecretPrefix = tupleToArray(sharedSecretData).prefix(32)
let reversedSharedSecret = sharedSecretPrefix.reversed()
let iv = opts.iv.hexa
let newXValue = reversedSharedSecret.hexa
let hash = SHA2(variant: .sha512).calculate(for: newXValue.hexa).hexa
let AesEncryptionKey = hash.prefix(64)

var result: String = ""
let aesEncryptionKey = hash.prefix(64)
do {
// AES-CBCblock-256
let aes = try AES(key: AesEncryptionKey.hexa, blockMode: CBC(iv: iv), padding: .pkcs7)
let decrypt = try aes.decrypt(opts.ciphertext.bytes)
result = decrypt.hexa
let aes = try AES(key: aesEncryptionKey.hexa, blockMode: CBC(iv: iv), padding: .pkcs7)
let decrypt = try aes.decrypt(opts.ciphertext.hexa)
let data = Data(decrypt)
result = String(data: data, encoding: .utf8) ?? ""
} catch let err {
result = TorusUtilError.decodingFailed(err.localizedDescription).debugDescription
throw err
}
return Data(hex: result)
return result
}

func encryptData(publicKey: String, msg: BigInt) throws -> Ecies {
// Generate ephemeral key pair
let ephemeralPrivateKey = P256.KeyAgreement.PrivateKey()
let ephemeralPublicKey = ephemeralPrivateKey.publicKey.rawRepresentation

// Convert public key to `P256.KeyAgreement.PublicKey` type
guard let recipientPublicKey = try? P256.KeyAgreement.PublicKey(rawRepresentation: Data(hex: publicKey)) else {
throw TorusUtilError.runtime("invalid public key")
func encryptData(privkeyHex: String, _ dataToEncrypt: String) throws -> String {
guard let pubKey = SECP256K1.privateToPublic(privateKey: privkeyHex.hexa.data)?.web3.hexString.web3.noHexPrefix else {
throw TorusUtilError.runtime("Invalid private key hex")
}

// Generate shared secret using ECDH
let sharedSecret = try ephemeralPrivateKey.sharedSecretFromKeyAgreement(with: recipientPublicKey)

// Derive encryption key, IV, and MAC key from shared secret
let encryptionKey = sharedSecret.hkdfDerivedSymmetricKey(using: SHA256.self, salt: Data(), sharedInfo: Data(), outputByteCount: 16)

// TODO: need to check if this iv and macKeyData is really needed
let iv = AES.GCM.Nonce()
let macKey = sharedSecret.hkdfDerivedSymmetricKey(using: SHA256.self, salt: Data(), sharedInfo: Data(), outputByteCount: 32)
let macKeyData = Data(macKey.withUnsafeBytes { Data($0) })

// Encrypt the message
let messageData = msg.serialize()
let sealedBox = try AES.GCM.seal(messageData, using: encryptionKey, nonce: iv, authenticating: macKeyData)
// let sealedBox = try AES.GCM.seal(messageData, using: encryptionKey, nonce: iv)

// Create the Ecies struct
let ecies = Ecies(iv: Data(sealedBox.nonce), ephemPublicKey: ephemeralPublicKey, ciphertext: sealedBox.ciphertext, mac: sealedBox.tag)

return ecies
let encParams = try encrypt(publicKey: pubKey, msg: dataToEncrypt, opts: nil)
let data = try JSONEncoder().encode(encParams)
guard let string = String(data: data, encoding: .utf8) else { throw TorusUtilError.runtime("Invalid String from enc Params") }
return string
}

private func encrypt(publicKey: String, msg: String, opts: Ecies? = nil) throws -> Ecies {
guard let ephemPrivateKey = SECP256K1.generatePrivateKey(), let ephemPublicKey = SECP256K1.privateToPublic(privateKey: ephemPrivateKey)
else {
throw TorusUtilError.runtime("Private key generation failed")
}
let ephermalPublicKey = publicKey.strip04Prefix()
let ephermalPublicKeyBytes = ephermalPublicKey.hexa
var ephermOne = ephermalPublicKeyBytes.prefix(32)
var ephermTwo = ephermalPublicKeyBytes.suffix(32)
ephermOne.reverse(); ephermTwo.reverse()
ephermOne.append(contentsOf: ephermTwo)
let ephemPubKey = secp256k1_pubkey.init(data: array32toTuple(Array(ephermOne)))
guard
// Calculate g^a^b, i.e., Shared Key
// let data = inprivateKey
let sharedSecret = SECP256K1.ecdh(pubKey: ephemPubKey, privateKey: ephemPrivateKey)
else {
throw TorusUtilError.runtime("ECDH error")
}

let sharedSecretData = sharedSecret.data
let sharedSecretPrefix = Array(tupleToArray(sharedSecretData).prefix(32))
let reversedSharedSecret = sharedSecretPrefix.uint8Reverse()
let hash = SHA2(variant: .sha512).calculate(for: Array(reversedSharedSecret))
let iv: [UInt8] = (opts?.iv ?? SECP256K1.randomBytes(length: 16)?.toHexString())?.hexa ?? []
let encryptionKey = Array(hash.prefix(32))
let macKey = Array(hash.suffix(32))
do {
// AES-CBCblock-256
let aes = try AES(key: encryptionKey, blockMode: CBC(iv: iv), padding: .pkcs7)
let encrypt = try aes.encrypt(msg.bytes)
let data = Data(encrypt)
let ciphertext = data
var dataToMac: [UInt8] = iv
dataToMac.append(contentsOf: [UInt8](ephemPublicKey.data))
dataToMac.append(contentsOf: [UInt8](ciphertext.data))
let mac = try? HMAC(key: macKey, variant: .sha2(.sha256)).authenticate(dataToMac)
return .init(iv: iv.toHexString(), ephemPublicKey: ephemPublicKey.toHexString(),
ciphertext: ciphertext.toHexString(), mac: mac?.toHexString() ?? "")
} catch let err {
throw err
}
}




// MARK: - decrypt shares
Expand Down Expand Up @@ -1642,4 +1663,15 @@ extension TorusUtils {
func array32toTuple(_ arr: [UInt8]) -> (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) {
return (arr[0] as UInt8, arr[1] as UInt8, arr[2] as UInt8, arr[3] as UInt8, arr[4] as UInt8, arr[5] as UInt8, arr[6] as UInt8, arr[7] as UInt8, arr[8] as UInt8, arr[9] as UInt8, arr[10] as UInt8, arr[11] as UInt8, arr[12] as UInt8, arr[13] as UInt8, arr[14] as UInt8, arr[15] as UInt8, arr[16] as UInt8, arr[17] as UInt8, arr[18] as UInt8, arr[19] as UInt8, arr[20] as UInt8, arr[21] as UInt8, arr[22] as UInt8, arr[23] as UInt8, arr[24] as UInt8, arr[25] as UInt8, arr[26] as UInt8, arr[27] as UInt8, arr[28] as UInt8, arr[29] as UInt8, arr[30] as UInt8, arr[31] as UInt8, arr[32] as UInt8, arr[33] as UInt8, arr[34] as UInt8, arr[35] as UInt8, arr[36] as UInt8, arr[37] as UInt8, arr[38] as UInt8, arr[39] as UInt8, arr[40] as UInt8, arr[41] as UInt8, arr[42] as UInt8, arr[43] as UInt8, arr[44] as UInt8, arr[45] as UInt8, arr[46] as UInt8, arr[47] as UInt8, arr[48] as UInt8, arr[49] as UInt8, arr[50] as UInt8, arr[51] as UInt8, arr[52] as UInt8, arr[53] as UInt8, arr[54] as UInt8, arr[55] as UInt8, arr[56] as UInt8, arr[57] as UInt8, arr[58] as UInt8, arr[59] as UInt8, arr[60] as UInt8, arr[61] as UInt8, arr[62] as UInt8, arr[63] as UInt8)
}

}

extension Array where Element == UInt8 {
func uint8Reverse() -> Array {
var revArr = [Element]()
for arrayIndex in stride(from: self.count - 1, through: 0, by: -1) {
revArr.append(self[arrayIndex])
}
return revArr
}
}
14 changes: 7 additions & 7 deletions Sources/TorusUtils/Helpers/Common.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ func thresholdSame<T: Equatable>(arr: [T], t: Int) -> T? {
}

func encParamsBufToHex(encParams: Ecies) -> EciesHex {
let ivString = encParams.iv.hexString
let ephemPublicKeyString = encParams.ephemPublicKey.hexString
let ciphertextString = encParams.ciphertext.hexString
let macString = encParams.mac.hexString
let ivString = encParams.iv
let ephemPublicKeyString = encParams.ephemPublicKey
let ciphertextString = encParams.ciphertext
let macString = encParams.mac

return EciesHex(iv: ivString,
ephemPublicKey: ephemPublicKeyString,
Expand All @@ -75,9 +75,9 @@ func encParamsBufToHex(encParams: Ecies) -> EciesHex {


func encParamsHexToBuf(eciesData: EciesHexOmitCiphertext) -> EciesOmitCiphertext {
return EciesOmitCiphertext(iv: Data(hex: eciesData.iv),
ephemPublicKey: Data(hex: eciesData.ephemPublicKey),
mac: Data(hex: eciesData.mac))
return EciesOmitCiphertext(iv: eciesData.iv,
ephemPublicKey: eciesData.ephemPublicKey,
mac: eciesData.mac)
}


Expand Down
25 changes: 9 additions & 16 deletions Sources/TorusUtils/Interfaces/Ecies.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import Foundation

protocol EciesProtocol {
var iv: Data { get }
var ephemPublicKey: Data { get }
var ciphertext: Data { get }
var mac: Data { get }
}

struct EciesHex : Codable {
let iv: String
let ephemPublicKey: String
Expand Down Expand Up @@ -35,13 +28,13 @@ struct EciesHexOmitCiphertext {
var mode: String?
}

public struct Ecies: EciesProtocol {
var iv: Data
var ephemPublicKey: Data
var ciphertext: Data
var mac: Data
public struct Ecies: Codable {
var iv: String
var ephemPublicKey: String
var ciphertext: String
var mac: String

init(iv: Data, ephemPublicKey: Data, ciphertext: Data, mac: Data) {
init(iv: String, ephemPublicKey: String, ciphertext: String, mac: String) {
self.iv = iv
self.ephemPublicKey = ephemPublicKey
self.ciphertext = ciphertext
Expand All @@ -50,7 +43,7 @@ public struct Ecies: EciesProtocol {
}

struct EciesOmitCiphertext {
var iv: Data
var ephemPublicKey: Data
var mac: Data
var iv: String
var ephemPublicKey: String
var mac: String
}
3 changes: 2 additions & 1 deletion Sources/TorusUtils/Interfaces/ImportedShare.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Foundation
import BigInt

struct ImportedShare {
let pubKeyX: String
let pubKeyY: String
let encryptedShare: String
let encryptedShareMetadata: EciesHex
let nodeIndex: Int
let nodeIndex: BigUInt
let keyType: String
let nonceData: String
let nonceSignature: String
Expand Down
2 changes: 1 addition & 1 deletion Sources/TorusUtils/Polynomial.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public struct Polynomial {
var shares: ShareMap = [:]
for x in 0..<shareIndexes.count {
let hexString = shareIndexes[x].serialize().toHexString()
shares[hexString] = Share(shareIndex: BNString.bn(shareIndexes[x]), share: BNString.bn(polyEval(x: shareIndexes[x])))
shares[hexString] = Share(shareIndex: shareIndexes[x], share: polyEval(x: shareIndexes[x]))
}
return shares
}
Expand Down
10 changes: 5 additions & 5 deletions Sources/TorusUtils/Share.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ class Share {
var share: BigInt
var shareIndex: BigInt

init(shareIndex: BNString, share: BNString) {
self.share = BigInt(share.toString()!, radix: 16)!
self.shareIndex = BigInt(shareIndex.toString()!, radix: 16)!
init(shareIndex: BigInt, share: BigInt) {
self.share = share
self.shareIndex = shareIndex
}

static func fromJSON(value: StringifiedType) -> Share? {
guard let shareIndex = value["shareIndex"] as? BNString,
let share = value["share"] as? BNString else {
guard let shareIndex = value["shareIndex"] as? BigInt,
let share = value["share"] as? BigInt else {
return nil
}

Expand Down

0 comments on commit 95e41a8

Please sign in to comment.