mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
no message
This commit is contained in:
@@ -362,6 +362,16 @@
|
||||
D08F4A671E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */; };
|
||||
D08F4A691E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */; };
|
||||
D08F4A6A1E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */; };
|
||||
D093D7EB206413C900BC3599 /* SecureIdPassportIdentity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7EA206413C900BC3599 /* SecureIdPassportIdentity.swift */; };
|
||||
D093D7EC206413C900BC3599 /* SecureIdPassportIdentity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7EA206413C900BC3599 /* SecureIdPassportIdentity.swift */; };
|
||||
D093D7EE206413F600BC3599 /* SecureIdDataTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7ED206413F600BC3599 /* SecureIdDataTypes.swift */; };
|
||||
D093D7EF206413F600BC3599 /* SecureIdDataTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7ED206413F600BC3599 /* SecureIdDataTypes.swift */; };
|
||||
D093D7F12064194600BC3599 /* SecureIdIdentityField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F02064194600BC3599 /* SecureIdIdentityField.swift */; };
|
||||
D093D7F22064194600BC3599 /* SecureIdIdentityField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F02064194600BC3599 /* SecureIdIdentityField.swift */; };
|
||||
D093D7F520641A4900BC3599 /* SecureIdPhoneField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F420641A4900BC3599 /* SecureIdPhoneField.swift */; };
|
||||
D093D7F620641A4900BC3599 /* SecureIdPhoneField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F420641A4900BC3599 /* SecureIdPhoneField.swift */; };
|
||||
D093D7F920641AA500BC3599 /* SecureIdEmailField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F820641AA500BC3599 /* SecureIdEmailField.swift */; };
|
||||
D093D7FA20641AA500BC3599 /* SecureIdEmailField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F820641AA500BC3599 /* SecureIdEmailField.swift */; };
|
||||
D099D7461EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099D7451EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift */; };
|
||||
D099D7471EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099D7451EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift */; };
|
||||
D099D7491EEF418D00A3128C /* HistoryViewChannelStateValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099D7481EEF418D00A3128C /* HistoryViewChannelStateValidation.swift */; };
|
||||
@@ -499,6 +509,8 @@
|
||||
D0BE303B20619EE800FBE6D8 /* SecureIdForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE303920619EE800FBE6D8 /* SecureIdForm.swift */; };
|
||||
D0BE303D2061A29100FBE6D8 /* RequestSecureIdForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */; };
|
||||
D0BE303E2061A29100FBE6D8 /* RequestSecureIdForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */; };
|
||||
D0BE304B20627D9800FBE6D8 /* AccessSecureId.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE304A20627D9800FBE6D8 /* AccessSecureId.swift */; };
|
||||
D0BE304C20627D9800FBE6D8 /* AccessSecureId.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE304A20627D9800FBE6D8 /* AccessSecureId.swift */; };
|
||||
D0BE383E1E7C5995000079AF /* MediaPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE383D1E7C5995000079AF /* MediaPool.swift */; };
|
||||
D0BE383F1E7C5995000079AF /* MediaPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE383D1E7C5995000079AF /* MediaPool.swift */; };
|
||||
D0BEAF5D1E54941B00BD963D /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5C1E54941B00BD963D /* Authorization.swift */; };
|
||||
@@ -840,6 +852,11 @@
|
||||
D08CAA8B1ED81EDF0000FDA8 /* Localizations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Localizations.swift; sourceTree = "<group>"; };
|
||||
D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizeInstalledStickerPacksOperations.swift; sourceTree = "<group>"; };
|
||||
D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeInstalledStickerPacksOperations.swift; sourceTree = "<group>"; };
|
||||
D093D7EA206413C900BC3599 /* SecureIdPassportIdentity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdPassportIdentity.swift; sourceTree = "<group>"; };
|
||||
D093D7ED206413F600BC3599 /* SecureIdDataTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdDataTypes.swift; sourceTree = "<group>"; };
|
||||
D093D7F02064194600BC3599 /* SecureIdIdentityField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdIdentityField.swift; sourceTree = "<group>"; };
|
||||
D093D7F420641A4900BC3599 /* SecureIdPhoneField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdPhoneField.swift; sourceTree = "<group>"; };
|
||||
D093D7F820641AA500BC3599 /* SecureIdEmailField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdEmailField.swift; sourceTree = "<group>"; };
|
||||
D099D7451EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelMessageStateVersionAttribute.swift; sourceTree = "<group>"; };
|
||||
D099D7481EEF418D00A3128C /* HistoryViewChannelStateValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistoryViewChannelStateValidation.swift; sourceTree = "<group>"; };
|
||||
D099EA1B1DE72867001AF5A8 /* PeerCommands.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerCommands.swift; sourceTree = "<group>"; };
|
||||
@@ -922,6 +939,7 @@
|
||||
D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TogglePeerChatPinned.swift; sourceTree = "<group>"; };
|
||||
D0BE303920619EE800FBE6D8 /* SecureIdForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdForm.swift; sourceTree = "<group>"; };
|
||||
D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestSecureIdForm.swift; sourceTree = "<group>"; };
|
||||
D0BE304A20627D9800FBE6D8 /* AccessSecureId.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessSecureId.swift; sourceTree = "<group>"; };
|
||||
D0BE383D1E7C5995000079AF /* MediaPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaPool.swift; sourceTree = "<group>"; };
|
||||
D0BEAF5C1E54941B00BD963D /* Authorization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Authorization.swift; sourceTree = "<group>"; };
|
||||
D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountManager.swift; sourceTree = "<group>"; };
|
||||
@@ -1479,6 +1497,42 @@
|
||||
name = Localization;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D093D7E82064135300BC3599 /* Fields */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D093D7ED206413F600BC3599 /* SecureIdDataTypes.swift */,
|
||||
D093D7E92064135A00BC3599 /* Identity */,
|
||||
D093D7F320641A3F00BC3599 /* Phone */,
|
||||
D093D7F720641A9600BC3599 /* Email */,
|
||||
);
|
||||
name = Fields;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D093D7E92064135A00BC3599 /* Identity */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D093D7F02064194600BC3599 /* SecureIdIdentityField.swift */,
|
||||
D093D7EA206413C900BC3599 /* SecureIdPassportIdentity.swift */,
|
||||
);
|
||||
name = Identity;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D093D7F320641A3F00BC3599 /* Phone */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D093D7F420641A4900BC3599 /* SecureIdPhoneField.swift */,
|
||||
);
|
||||
name = Phone;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D093D7F720641A9600BC3599 /* Email */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D093D7F820641AA500BC3599 /* SecureIdEmailField.swift */,
|
||||
);
|
||||
name = Email;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D09D8BF71D4FAB1D0081DBEC = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1569,6 +1623,8 @@
|
||||
children = (
|
||||
D0BE303920619EE800FBE6D8 /* SecureIdForm.swift */,
|
||||
D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */,
|
||||
D0BE304A20627D9800FBE6D8 /* AccessSecureId.swift */,
|
||||
D093D7E82064135300BC3599 /* Fields */,
|
||||
);
|
||||
name = "Secure ID";
|
||||
sourceTree = "<group>";
|
||||
@@ -1848,6 +1904,7 @@
|
||||
D021E0DF1DB539FC00C6B04F /* StickerPack.swift in Sources */,
|
||||
D03B0D091D62255C00955575 /* EnqueueMessage.swift in Sources */,
|
||||
D0DFD5DF1FCDBCFD0039B3B1 /* CachedSentMediaReferences.swift in Sources */,
|
||||
D093D7EE206413F600BC3599 /* SecureIdDataTypes.swift in Sources */,
|
||||
D00D343C1E6EC9770057B307 /* TelegramMediaGame.swift in Sources */,
|
||||
D033FEB01E61EB0200644997 /* PeerReportStatus.swift in Sources */,
|
||||
D050F2511E4A59C200988324 /* JoinLink.swift in Sources */,
|
||||
@@ -1895,6 +1952,7 @@
|
||||
D0DF0CA81D82BF32008AEB01 /* PeerParticipants.swift in Sources */,
|
||||
D0FA8BA71E1FA6DF001E855B /* TelegramSecretChat.swift in Sources */,
|
||||
D03B0D5F1D631A6900955575 /* Serialization.swift in Sources */,
|
||||
D093D7F920641AA500BC3599 /* SecureIdEmailField.swift in Sources */,
|
||||
D0C44B611FC616E200227BE0 /* SearchGroupMembers.swift in Sources */,
|
||||
D03B0D441D6319F900955575 /* CloudFileMediaResource.swift in Sources */,
|
||||
D018D3371E648ACF00C5E089 /* CreateChannel.swift in Sources */,
|
||||
@@ -1988,6 +2046,7 @@
|
||||
D0F7AB2C1DCE889D009AD9A1 /* EditedMessageAttribute.swift in Sources */,
|
||||
D0FA8BAA1E1FB76E001E855B /* ManagedSecretChatOutgoingOperations.swift in Sources */,
|
||||
D00D97C71E32901700E5C2B6 /* PeerInputActivity.swift in Sources */,
|
||||
D093D7EB206413C900BC3599 /* SecureIdPassportIdentity.swift in Sources */,
|
||||
D0FA8BAD1E1FD6E2001E855B /* MemoryBufferExtensions.swift in Sources */,
|
||||
D03B0CBF1D62234A00955575 /* Log.swift in Sources */,
|
||||
C2FD33E41E687BF1008D13D4 /* PeerPhotoUpdater.swift in Sources */,
|
||||
@@ -2023,6 +2082,7 @@
|
||||
D033FEB61E61F3F900644997 /* BlockedPeers.swift in Sources */,
|
||||
D00C7CCC1E3620C30080C3D5 /* CachedChannelParticipants.swift in Sources */,
|
||||
D09BB6B41DB02C2B00A905C0 /* PendingMessageManager.swift in Sources */,
|
||||
D093D7F520641A4900BC3599 /* SecureIdPhoneField.swift in Sources */,
|
||||
D0B167231F9F972E00976B40 /* LoggingSettings.swift in Sources */,
|
||||
D0BC387B1E40D2880044D6FE /* TogglePeerChatPinned.swift in Sources */,
|
||||
D0BB7C5A1E5C8074001527C3 /* ChannelParticipants.swift in Sources */,
|
||||
@@ -2038,6 +2098,7 @@
|
||||
D01C7ED31EF5DF83008305F1 /* LimitsConfiguration.swift in Sources */,
|
||||
D0F02CE51E9926C40065DEE2 /* ManagedConfigurationUpdates.swift in Sources */,
|
||||
D0528E6A1E65DD2100E2FEF5 /* WebpagePreview.swift in Sources */,
|
||||
D0BE304B20627D9800FBE6D8 /* AccessSecureId.swift in Sources */,
|
||||
D0BEAF5D1E54941B00BD963D /* Authorization.swift in Sources */,
|
||||
D0C26D6C1FE286C3004ABF18 /* FetchChatList.swift in Sources */,
|
||||
D0B843831DA6EDB8005F29E1 /* CachedGroupData.swift in Sources */,
|
||||
@@ -2095,6 +2156,7 @@
|
||||
D021E0E21DB5401A00C6B04F /* StickerManagement.swift in Sources */,
|
||||
D0BC38701E40853E0044D6FE /* UpdatePeers.swift in Sources */,
|
||||
D0F3A8A81E82CD7D00B4C64C /* UpdatePeerChatInterfaceState.swift in Sources */,
|
||||
D093D7F12064194600BC3599 /* SecureIdIdentityField.swift in Sources */,
|
||||
D03B0CE21D62249B00955575 /* InlineBotMessageAttribute.swift in Sources */,
|
||||
D0AB0B9A1D666520002C78E7 /* ManagedSynchronizePeerReadStates.swift in Sources */,
|
||||
D03B0D5B1D631A6900955575 /* Buffer.swift in Sources */,
|
||||
@@ -2161,6 +2223,7 @@
|
||||
C26A37EF1E5E0C41006977AC /* ChannelParticipants.swift in Sources */,
|
||||
D00D343D1E6EC9770057B307 /* TelegramMediaGame.swift in Sources */,
|
||||
D0C26D6A1FE02402004ABF18 /* ManagedSynchronizeGroupedPeersOperations.swift in Sources */,
|
||||
D093D7F22064194600BC3599 /* SecureIdIdentityField.swift in Sources */,
|
||||
D01C7F051EFC1C49008305F1 /* DeviceContact.swift in Sources */,
|
||||
D050F26A1E4A5B6D00988324 /* ManagedGlobalNotificationSettings.swift in Sources */,
|
||||
D050F26B1E4A5B6D00988324 /* ApplyMaxReadIndexInteractively.swift in Sources */,
|
||||
@@ -2252,6 +2315,7 @@
|
||||
D0BEAF611E54ACF900BD963D /* AccountManager.swift in Sources */,
|
||||
D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */,
|
||||
D0B8442B1DAB91E0005F29E1 /* NBMetadataCore.m in Sources */,
|
||||
D093D7EF206413F600BC3599 /* SecureIdDataTypes.swift in Sources */,
|
||||
D03DC9141F82F89D001D584C /* RegularChatState.swift in Sources */,
|
||||
D0C44B621FC616E200227BE0 /* SearchGroupMembers.swift in Sources */,
|
||||
D00C7CD01E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */,
|
||||
@@ -2280,8 +2344,10 @@
|
||||
D0B8442A1DAB91E0005F29E1 /* NBAsYouTypeFormatter.m in Sources */,
|
||||
D07047B51F3DF1FE00F6A8D4 /* ConsumablePersonalMentionMessageAttribute.swift in Sources */,
|
||||
D0448C8F1E22993C005A61A7 /* ProcessSecretChatIncomingDecryptedOperations.swift in Sources */,
|
||||
D093D7F620641A4900BC3599 /* SecureIdPhoneField.swift in Sources */,
|
||||
D0C26D6D1FE286C3004ABF18 /* FetchChatList.swift in Sources */,
|
||||
D073CE6E1DCBCF17007511FD /* ForwardSourceInfoAttribute.swift in Sources */,
|
||||
D093D7FA20641AA500BC3599 /* SecureIdEmailField.swift in Sources */,
|
||||
D05A32E21E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift in Sources */,
|
||||
D0613FD01E60520700202CDB /* ChannelMembers.swift in Sources */,
|
||||
D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */,
|
||||
@@ -2302,6 +2368,7 @@
|
||||
D0B418A91D7E0597004562A4 /* Buffer.swift in Sources */,
|
||||
D02ABC821E310E5D00CAE539 /* ManagedCloudChatRemoveMessagesOperations.swift in Sources */,
|
||||
C2FD33E51E687BF1008D13D4 /* PeerPhotoUpdater.swift in Sources */,
|
||||
D0BE304C20627D9800FBE6D8 /* AccessSecureId.swift in Sources */,
|
||||
D0B8442E1DAB91E0005F29E1 /* NBMetadataCoreTestMapper.m in Sources */,
|
||||
D01A21AD1F38D10E00DDA104 /* SavedStickerItem.swift in Sources */,
|
||||
D03C53731DAD5CA9004C17B3 /* CachedGroupData.swift in Sources */,
|
||||
@@ -2396,6 +2463,7 @@
|
||||
D099D7471EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift in Sources */,
|
||||
D058E0D21E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */,
|
||||
D03C536F1DAD5CA9004C17B3 /* BotInfo.swift in Sources */,
|
||||
D093D7EC206413C900BC3599 /* SecureIdPassportIdentity.swift in Sources */,
|
||||
D0FA8BBA1E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */,
|
||||
D033FEB41E61F3C000644997 /* ReportPeer.swift in Sources */,
|
||||
D0FA8BAE1E1FD6E2001E855B /* MemoryBufferExtensions.swift in Sources */,
|
||||
|
||||
185
TelegramCore/AccessSecureId.swift
Normal file
185
TelegramCore/AccessSecureId.swift
Normal file
@@ -0,0 +1,185 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import MtProtoKitMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import MtProtoKitDynamic
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
import TelegramCorePrivateModule
|
||||
|
||||
private enum GenerateSecureSecretError {
|
||||
case generic
|
||||
}
|
||||
|
||||
func decryptedSecureSecret(encryptedSecretData: Data, password: String) -> Data? {
|
||||
guard let passwordData = password.data(using: .utf8) else {
|
||||
return nil
|
||||
}
|
||||
let passwordHash = sha512Digest(passwordData)
|
||||
let secretKey = passwordHash.subdata(in: 0 ..< 32)
|
||||
let iv = passwordHash.subdata(in: 32 ..< (32 + 16))
|
||||
|
||||
var decryptedSecret = Data(count: encryptedSecretData.count)
|
||||
|
||||
guard decryptedSecret.withUnsafeMutableBytes({ (decryptedSecretBytes: UnsafeMutablePointer<Int8>) -> Bool in
|
||||
return secretKey.withUnsafeBytes { (secretKeyBytes: UnsafePointer<Int8>) -> Bool in
|
||||
return iv.withUnsafeBytes { (ivBytes: UnsafePointer<Int8>) -> Bool in
|
||||
return encryptedSecretData.withUnsafeBytes { (encryptedSecretDataBytes: UnsafePointer<Int8>) -> Bool in
|
||||
var processedCount: Int = 0
|
||||
let result = CCCrypt(CCOperation(kCCDecrypt), CCAlgorithm(kCCAlgorithmAES128), 0, secretKeyBytes, secretKey.count, ivBytes, encryptedSecretDataBytes, encryptedSecretData.count, decryptedSecretBytes, decryptedSecret.count, &processedCount)
|
||||
if result != kCCSuccess {
|
||||
return false
|
||||
}
|
||||
if processedCount != decryptedSecret.count {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard decryptedSecret.withUnsafeMutableBytes({ (bytes: UnsafeMutablePointer<UInt8>) -> Bool in
|
||||
var checksum: UInt32 = 0
|
||||
for i in 0 ..< decryptedSecret.count {
|
||||
checksum += UInt32(bytes.advanced(by: i).pointee)
|
||||
checksum = checksum % 255
|
||||
}
|
||||
if checksum == 239 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return decryptedSecret
|
||||
}
|
||||
|
||||
func encryptedSecureSecret(secretData: Data, password: String) -> Data? {
|
||||
guard let passwordData = password.data(using: .utf8) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let passwordHash = sha512Digest(passwordData)
|
||||
let secretKey = passwordHash.subdata(in: 0 ..< 32)
|
||||
let iv = passwordHash.subdata(in: 32 ..< (32 + 16))
|
||||
|
||||
var encryptedSecret = Data(count: secretData.count)
|
||||
|
||||
guard encryptedSecret.withUnsafeMutableBytes({ (encryptedSecretBytes: UnsafeMutablePointer<Int8>) -> Bool in
|
||||
return secretKey.withUnsafeBytes { (secretKeyBytes: UnsafePointer<Int8>) -> Bool in
|
||||
return iv.withUnsafeBytes { (ivBytes: UnsafePointer<Int8>) -> Bool in
|
||||
return secretData.withUnsafeBytes { (secretDataBytes: UnsafePointer<Int8>) -> Bool in
|
||||
var processedCount: Int = 0
|
||||
let result = CCCrypt(CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES128), 0, secretKeyBytes, secretKey.count, ivBytes, secretDataBytes, secretData.count, encryptedSecretBytes, encryptedSecret.count, &processedCount)
|
||||
if result != kCCSuccess {
|
||||
return false
|
||||
}
|
||||
if processedCount != encryptedSecret.count {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
if decryptedSecureSecret(encryptedSecretData: encryptedSecret, password: password) != secretData {
|
||||
return nil
|
||||
}
|
||||
|
||||
return encryptedSecret
|
||||
}
|
||||
|
||||
private func generateSecureSecret(network: Network, password: String) -> Signal<Data, GenerateSecureSecretError> {
|
||||
var secretData = Data(count: 32)
|
||||
guard secretData.withUnsafeMutableBytes({ (bytes: UnsafeMutablePointer<Int8>) -> Bool in
|
||||
let copyResult = SecRandomCopyBytes(nil, 32, bytes)
|
||||
return copyResult == errSecSuccess
|
||||
}) else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
secretData.withUnsafeMutableBytes({ (bytes: UnsafeMutablePointer<UInt8>) in
|
||||
while true {
|
||||
var checksum: UInt32 = 0
|
||||
for i in 0 ..< secretData.count {
|
||||
checksum += UInt32(bytes.advanced(by: i).pointee)
|
||||
checksum = checksum % 255
|
||||
}
|
||||
if checksum == 239 {
|
||||
break
|
||||
} else {
|
||||
var i = secretData.count - 1
|
||||
inner: while i >= 0 {
|
||||
var byte = bytes.advanced(by: i).pointee
|
||||
if byte != 0xff {
|
||||
byte += 1
|
||||
bytes.advanced(by: i).pointee = byte
|
||||
break inner
|
||||
} else {
|
||||
byte = 0
|
||||
bytes.advanced(by: i).pointee = byte
|
||||
}
|
||||
i -= 1
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
guard let encryptedSecret = encryptedSecureSecret(secretData: secretData, password: password) else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
return updateTwoStepVerificationSecureSecret(network: network, password: password, updatedSecret: encryptedSecret)
|
||||
|> mapError { _ -> GenerateSecureSecretError in
|
||||
return .generic
|
||||
}
|
||||
|> map { _ -> Data in
|
||||
return secretData
|
||||
}
|
||||
}
|
||||
|
||||
public struct SecureIdAccessContext {
|
||||
let secret: Data
|
||||
}
|
||||
|
||||
public enum SecureIdAccessError {
|
||||
case generic
|
||||
case passwordError(AuthorizationPasswordVerificationError)
|
||||
case secretPasswordMismatch
|
||||
}
|
||||
|
||||
public func accessSecureId(network: Network, password: String) -> Signal<SecureIdAccessContext, SecureIdAccessError> {
|
||||
return requestTwoStepVerifiationSettings(network: network, password: password)
|
||||
|> mapError { error -> SecureIdAccessError in
|
||||
return .passwordError(error)
|
||||
}
|
||||
|> mapToSignal { settings -> Signal<SecureIdAccessContext, SecureIdAccessError> in
|
||||
if let secureSecret = settings.secureSecret {
|
||||
if let decryptedSecret = decryptedSecureSecret(encryptedSecretData: secureSecret, password: "q") { //password
|
||||
return .single(SecureIdAccessContext(secret: decryptedSecret))
|
||||
} else {
|
||||
return .fail(.secretPasswordMismatch)
|
||||
}
|
||||
} else {
|
||||
return generateSecureSecret(network: network, password: password)
|
||||
|> mapError { _ -> SecureIdAccessError in
|
||||
return SecureIdAccessError.generic
|
||||
}
|
||||
|> map { decryptedSecret in
|
||||
return SecureIdAccessContext(secret: decryptedSecret)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -336,12 +336,12 @@ public func accountWithId(networkArguments: NetworkInitializationArguments, id:
|
||||
}
|
||||
|
||||
public struct TwoStepAuthData {
|
||||
let nextSalt: Data
|
||||
let currentSalt: Data?
|
||||
let hasRecovery: Bool
|
||||
let currentHint: String?
|
||||
let unconfirmedEmailPattern: String?
|
||||
let secretRandom: Data
|
||||
public let nextSalt: Data
|
||||
public let currentSalt: Data?
|
||||
public let hasRecovery: Bool
|
||||
public let currentHint: String?
|
||||
public let unconfirmedEmailPattern: String?
|
||||
public let secretRandom: Data
|
||||
}
|
||||
|
||||
public func twoStepAuthData(_ network: Network) -> Signal<TwoStepAuthData, MTRpcError> {
|
||||
@@ -378,6 +378,17 @@ func sha256Digest(_ data : Data) -> Data {
|
||||
return res
|
||||
}
|
||||
|
||||
func sha512Digest(_ data : Data) -> Data {
|
||||
var res = Data()
|
||||
res.count = Int(CC_SHA512_DIGEST_LENGTH)
|
||||
res.withUnsafeMutableBytes { mutableBytes -> Void in
|
||||
data.withUnsafeBytes { bytes -> Void in
|
||||
CC_SHA512(bytes, CC_LONG(data.count), mutableBytes)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
public func verifyPassword(_ account: UnauthorizedAccount, password: String) -> Signal<Api.auth.Authorization, MTRpcError> {
|
||||
return twoStepAuthData(account.network)
|
||||
|> mapToSignal { authData -> Signal<Api.auth.Authorization, MTRpcError> in
|
||||
|
||||
@@ -13,7 +13,14 @@ public enum RequestSecureIdFormError {
|
||||
case generic
|
||||
}
|
||||
|
||||
private func parseFieldType(_ type: Api.AuthFieldType) -> SecureIdFieldType {
|
||||
public enum RequestedSecureIdField {
|
||||
case identity
|
||||
case address
|
||||
case phone
|
||||
case email
|
||||
}
|
||||
|
||||
private func parseRequestedFieldType(_ type: Api.AuthFieldType) -> RequestedSecureIdField {
|
||||
switch type {
|
||||
case .authFieldTypeIdentity:
|
||||
return .identity
|
||||
@@ -35,7 +42,7 @@ private func parseFileReference(_ file: Api.SecureFile) -> SecureIdFileReference
|
||||
}
|
||||
}
|
||||
|
||||
private func parseValue(_ value: Api.SecureValue) -> SecureIdFieldValue {
|
||||
/*private func parseValue(_ value: Api.SecureValue) -> SecureIdFieldValue {
|
||||
switch value {
|
||||
case let .secureValueEmpty(name):
|
||||
return SecureIdFieldValue(name: name, data: .none)
|
||||
@@ -46,16 +53,75 @@ private func parseValue(_ value: Api.SecureValue) -> SecureIdFieldValue {
|
||||
case let .secureValueText(name, text, hash):
|
||||
return SecureIdFieldValue(name: name, data: .text(text: text, hash: hash))
|
||||
}
|
||||
}*/
|
||||
|
||||
private func parseIdentityField(context: SecureIdAccessContext, value: Api.SecureValue, document: Api.SecureValue?) -> SecureIdIdentityField? {
|
||||
switch value {
|
||||
case let .secureValueData(name, data, hash, secret):
|
||||
return nil
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func parseField(_ field: Api.AuthField) -> SecureIdField {
|
||||
private func parsePhoneField(context: SecureIdAccessContext, value: Api.SecureValue) -> SecureIdPhoneField? {
|
||||
switch value {
|
||||
case let .secureValueText(name, text, _):
|
||||
return SecureIdPhoneField(rawValue: text)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func parseEmailField(context: SecureIdAccessContext, value: Api.SecureValue) -> SecureIdEmailField? {
|
||||
switch value {
|
||||
case let .secureValueText(name, text, _):
|
||||
return SecureIdEmailField(rawValue: text)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func parseFields(context: SecureIdAccessContext, fields: [Api.AuthField]) -> SecureIdFields {
|
||||
var result = SecureIdFields(identity: nil, phone: nil, email: nil)
|
||||
for field in fields {
|
||||
switch field {
|
||||
case let .authField(_, type, data, document):
|
||||
return SecureIdField(type: parseFieldType(type), value: parseValue(data))
|
||||
switch type {
|
||||
case .authFieldTypeIdentity:
|
||||
if let identity = parseIdentityField(context: context, value: data, document: document) {
|
||||
result.identity = .value(identity)
|
||||
} else {
|
||||
result.identity = .empty
|
||||
}
|
||||
case .authFieldTypeAddress:
|
||||
break
|
||||
case .authFieldTypePhone:
|
||||
if let phone = parsePhoneField(context: context, value: data) {
|
||||
result.phone = .value(phone)
|
||||
} else {
|
||||
result.phone = .empty
|
||||
}
|
||||
case .authFieldTypeEmail:
|
||||
if let email = parseEmailField(context: context, value: data) {
|
||||
result.email = .value(email)
|
||||
} else {
|
||||
result.email = .empty
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: PeerId, scope: [String], origin: String?, packageName: String?, bundleId: String?, publicKey: String?) -> Signal<SecureIdForm, RequestSecureIdFormError> {
|
||||
public struct EncryptedSecureIdForm {
|
||||
public let peerId: PeerId
|
||||
public let requestedFields: [RequestedSecureIdField]
|
||||
|
||||
let encryptedFields: [Api.AuthField]
|
||||
}
|
||||
|
||||
public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: PeerId, scope: [String], origin: String?, packageName: String?, bundleId: String?, publicKey: String?) -> Signal<EncryptedSecureIdForm, RequestSecureIdFormError> {
|
||||
if peerId.namespace != Namespaces.Peer.CloudUser {
|
||||
return .fail(.generic)
|
||||
}
|
||||
@@ -76,10 +142,10 @@ public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: Peer
|
||||
|> mapError { _ -> RequestSecureIdFormError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<SecureIdForm, RequestSecureIdFormError> in
|
||||
return postbox.modify { modifier -> SecureIdForm in
|
||||
|> mapToSignal { result -> Signal<EncryptedSecureIdForm, RequestSecureIdFormError> in
|
||||
return postbox.modify { modifier -> EncryptedSecureIdForm in
|
||||
switch result {
|
||||
case let .authorizationForm(_, botId, fields, acceptedFields, users):
|
||||
case let .authorizationForm(_, botId, fields, _, users):
|
||||
var peers: [Peer] = []
|
||||
for user in users {
|
||||
let parsed = TelegramUser(user: user)
|
||||
@@ -89,10 +155,17 @@ public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: Peer
|
||||
return updated
|
||||
})
|
||||
|
||||
let parsedFields = fields.map(parseField)
|
||||
|
||||
return SecureIdForm(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: botId), fields: parsedFields)
|
||||
return EncryptedSecureIdForm(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: botId), requestedFields: fields.map { field -> RequestedSecureIdField in
|
||||
switch field {
|
||||
case let .authField(_, type, data, document):
|
||||
return parseRequestedFieldType(type)
|
||||
}
|
||||
}, encryptedFields: fields)
|
||||
}
|
||||
} |> mapError { _ in return RequestSecureIdFormError.generic }
|
||||
}
|
||||
}
|
||||
|
||||
public func decryptedSecureIdForm(context: SecureIdAccessContext, form: EncryptedSecureIdForm) -> SecureIdForm? {
|
||||
return SecureIdForm(peerId: form.peerId, fields: parseFields(context: context, fields: form.encryptedFields))
|
||||
}
|
||||
|
||||
43
TelegramCore/SecureIdDataTypes.swift
Normal file
43
TelegramCore/SecureIdDataTypes.swift
Normal file
@@ -0,0 +1,43 @@
|
||||
import Foundation
|
||||
|
||||
public struct SecureIdDate: Equatable {
|
||||
private var timestamp: Int32
|
||||
|
||||
public init(timestamp: Int32) {
|
||||
self.timestamp = timestamp
|
||||
}
|
||||
|
||||
public static func ==(lhs: SecureIdDate, rhs: SecureIdDate) -> Bool {
|
||||
if lhs.timestamp != rhs.timestamp {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public enum SecureIdGender {
|
||||
case male
|
||||
case female
|
||||
}
|
||||
|
||||
public enum SecureIdFileReference: Equatable {
|
||||
case none
|
||||
case file(id: Int64, accessHash: Int64, size: Int32, datacenterId: Int32, fileHash: String)
|
||||
|
||||
public static func ==(lhs: SecureIdFileReference, rhs: SecureIdFileReference) -> Bool {
|
||||
switch lhs {
|
||||
case .none:
|
||||
if case .none = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .file(id, accessHash, size, datacenterId, fileHash):
|
||||
if case .file(id, accessHash, size, datacenterId, fileHash) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
TelegramCore/SecureIdEmailField.swift
Normal file
16
TelegramCore/SecureIdEmailField.swift
Normal file
@@ -0,0 +1,16 @@
|
||||
import Foundation
|
||||
|
||||
public struct SecureIdEmailField: Equatable {
|
||||
public let rawValue: String
|
||||
|
||||
public init(rawValue: String) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
public static func ==(lhs: SecureIdEmailField, rhs: SecureIdEmailField) -> Bool {
|
||||
if lhs.rawValue != rhs.rawValue {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -5,36 +5,77 @@ import Foundation
|
||||
import Postbox
|
||||
#endif
|
||||
|
||||
public enum SecureIdFieldType {
|
||||
case identity
|
||||
case address
|
||||
case phone
|
||||
case email
|
||||
public enum SecureIdFieldValue<T>: Equatable where T: Equatable {
|
||||
case empty
|
||||
case value(T)
|
||||
|
||||
public static func ==(lhs: SecureIdFieldValue<T>, rhs: SecureIdFieldValue<T>) -> Bool {
|
||||
switch lhs {
|
||||
case .empty:
|
||||
if case .empty = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .value(value):
|
||||
if case .value(value) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum SecureIdFileReference {
|
||||
case none
|
||||
case file(id: Int64, accessHash: Int64, size: Int32, datacenterId: Int32, fileHash: String)
|
||||
public struct SecureIdFields: Equatable {
|
||||
public var identity: SecureIdFieldValue<SecureIdIdentityField>?
|
||||
public var phone: SecureIdFieldValue<SecureIdPhoneField>?
|
||||
public var email: SecureIdFieldValue<SecureIdEmailField>?
|
||||
|
||||
public static func ==(lhs: SecureIdFields, rhs: SecureIdFields) -> Bool {
|
||||
if lhs.identity != rhs.identity {
|
||||
return false
|
||||
}
|
||||
if lhs.phone != rhs.phone {
|
||||
return false
|
||||
}
|
||||
if lhs.email != rhs.email {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public enum SecureIdFieldValueData {
|
||||
case none
|
||||
case data(data: Data, hash: String, secret: Data)
|
||||
case files(files: [SecureIdFileReference], hash: String, secret: Data)
|
||||
case text(text: String, hash: String)
|
||||
}
|
||||
public enum SecureIdField: Equatable {
|
||||
case identity(SecureIdIdentityField)
|
||||
case phone(SecureIdPhoneField)
|
||||
case email(SecureIdEmailField)
|
||||
|
||||
public struct SecureIdFieldValue {
|
||||
public let name: String
|
||||
public let data: SecureIdFieldValueData
|
||||
public static func ==(lhs: SecureIdField, rhs: SecureIdField) -> Bool {
|
||||
switch lhs {
|
||||
case let .identity(field):
|
||||
if case .identity(field) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .phone(field):
|
||||
if case .phone(field) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .email(field):
|
||||
if case .email(field) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct SecureIdField {
|
||||
public let type: SecureIdFieldType
|
||||
public let value: SecureIdFieldValue
|
||||
}
|
||||
|
||||
public struct SecureIdForm {
|
||||
public let peerId: PeerId
|
||||
public let fields: [SecureIdField]
|
||||
public let fields: SecureIdFields
|
||||
}
|
||||
|
||||
16
TelegramCore/SecureIdIdentityField.swift
Normal file
16
TelegramCore/SecureIdIdentityField.swift
Normal file
@@ -0,0 +1,16 @@
|
||||
import Foundation
|
||||
|
||||
public struct SecureIdIdentityField: Equatable {
|
||||
public var passport: SecureIdPassportIdentity?
|
||||
|
||||
public init(passport: SecureIdPassportIdentity?) {
|
||||
self.passport = passport
|
||||
}
|
||||
|
||||
public static func ==(lhs: SecureIdIdentityField, rhs: SecureIdIdentityField) -> Bool {
|
||||
if lhs.passport != rhs.passport {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
41
TelegramCore/SecureIdPassportIdentity.swift
Normal file
41
TelegramCore/SecureIdPassportIdentity.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
import Foundation
|
||||
|
||||
public struct SecureIdPassportIdentity: Equatable {
|
||||
public var id: String
|
||||
public var firstName: String
|
||||
public var lastName: String
|
||||
public var birthdate: SecureIdDate
|
||||
public var countryCode: String
|
||||
public var gender: SecureIdGender
|
||||
|
||||
public init(id: String, firstName: String, lastName: String, birthdate: SecureIdDate, countryCode: String, gender: SecureIdGender) {
|
||||
self.id = id
|
||||
self.firstName = firstName
|
||||
self.lastName = lastName
|
||||
self.birthdate = birthdate
|
||||
self.countryCode = countryCode
|
||||
self.gender = gender
|
||||
}
|
||||
|
||||
public static func ==(lhs: SecureIdPassportIdentity, rhs: SecureIdPassportIdentity) -> Bool {
|
||||
if lhs.id != rhs.id {
|
||||
return false
|
||||
}
|
||||
if lhs.firstName != rhs.firstName {
|
||||
return false
|
||||
}
|
||||
if lhs.lastName != rhs.lastName {
|
||||
return false
|
||||
}
|
||||
if lhs.birthdate != rhs.birthdate {
|
||||
return false
|
||||
}
|
||||
if lhs.countryCode != rhs.countryCode {
|
||||
return false
|
||||
}
|
||||
if lhs.gender != rhs.gender {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
16
TelegramCore/SecureIdPhoneField.swift
Normal file
16
TelegramCore/SecureIdPhoneField.swift
Normal file
@@ -0,0 +1,16 @@
|
||||
import Foundation
|
||||
|
||||
public struct SecureIdPhoneField: Equatable {
|
||||
public let rawValue: String
|
||||
|
||||
public init(rawValue: String) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
public static func ==(lhs: SecureIdPhoneField, rhs: SecureIdPhoneField) -> Bool {
|
||||
if lhs.rawValue != rhs.rawValue {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -29,10 +29,11 @@ public func twoStepVerificationConfiguration(account: Account) -> Signal<TwoStep
|
||||
|
||||
public struct TwoStepVerificationSettings {
|
||||
public let email: String
|
||||
public let secureSecret: Data?
|
||||
}
|
||||
|
||||
public func requestTwoStepVerifiationSettings(account: Account, password: String) -> Signal<TwoStepVerificationSettings, AuthorizationPasswordVerificationError> {
|
||||
return twoStepAuthData(account.network)
|
||||
public func requestTwoStepVerifiationSettings(network: Network, password: String) -> Signal<TwoStepVerificationSettings, AuthorizationPasswordVerificationError> {
|
||||
return twoStepAuthData(network)
|
||||
|> mapToSignal { authData -> Signal<TwoStepVerificationSettings, MTRpcError> in
|
||||
var data = Data()
|
||||
data.append(authData.currentSalt!)
|
||||
@@ -40,11 +41,11 @@ public func requestTwoStepVerifiationSettings(account: Account, password: String
|
||||
data.append(authData.currentSalt!)
|
||||
let currentPasswordHash = sha256Digest(data)
|
||||
|
||||
return account.network.request(Api.functions.account.getPasswordSettings(currentPasswordHash: Buffer(data: currentPasswordHash)), automaticFloodWait: false)
|
||||
return network.request(Api.functions.account.getPasswordSettings(currentPasswordHash: Buffer(data: currentPasswordHash)), automaticFloodWait: false)
|
||||
|> map { result -> TwoStepVerificationSettings in
|
||||
switch result {
|
||||
case let .passwordSettings(email, _):
|
||||
return TwoStepVerificationSettings(email: email)
|
||||
case let .passwordSettings(email, secureSecret):
|
||||
return TwoStepVerificationSettings(email: email, secureSecret: secureSecret.size == 0 ? nil : secureSecret.makeData())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,12 +75,25 @@ public enum UpdatedTwoStepVerificationPassword {
|
||||
case password(password: String, hint: String, email: String?)
|
||||
}
|
||||
|
||||
public func updateTwoStepVerificationPassword(account: Account, currentPassword: String?, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
|
||||
return twoStepAuthData(account.network)
|
||||
public func updateTwoStepVerificationPassword(network: Network, currentPassword: String?, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
|
||||
return twoStepAuthData(network)
|
||||
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { authData -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> in
|
||||
|> mapToSignal { authData -> Signal<(TwoStepAuthData, Data?), UpdateTwoStepVerificationPasswordError> in
|
||||
if authData.currentSalt != nil {
|
||||
return requestTwoStepVerifiationSettings(network: network, password: currentPassword ?? "")
|
||||
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
||||
return .generic
|
||||
}
|
||||
|> map { settings in
|
||||
return (authData, settings.secureSecret)
|
||||
}
|
||||
} else {
|
||||
return .single((authData, nil))
|
||||
}
|
||||
}
|
||||
|> mapToSignal { authData, secureSecret -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> in
|
||||
let currentPasswordHash: Buffer
|
||||
if let currentSalt = authData.currentSalt {
|
||||
var data = Data()
|
||||
@@ -100,7 +114,7 @@ public func updateTwoStepVerificationPassword(account: Account, currentPassword:
|
||||
flags |= (1 << 0)
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.account.updatePasswordSettings(currentPasswordHash: currentPasswordHash, newSettings: .passwordInputSettings(flags: flags, newSalt: Buffer(data: Data()), newPasswordHash: Buffer(data: Data()), hint: "", email: "", newSecureSecret: nil)), automaticFloodWait: false)
|
||||
return network.request(Api.functions.account.updatePasswordSettings(currentPasswordHash: currentPasswordHash, newSettings: .passwordInputSettings(flags: flags, newSalt: Buffer(data: Data()), newPasswordHash: Buffer(data: Data()), hint: "", email: "", newSecureSecret: nil)), automaticFloodWait: false)
|
||||
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
||||
return .generic
|
||||
}
|
||||
@@ -126,14 +140,24 @@ public func updateTwoStepVerificationPassword(account: Account, currentPassword:
|
||||
updatedData.append(password.data(using: .utf8, allowLossyConversion: true)!)
|
||||
updatedData.append(nextSalt)
|
||||
|
||||
var updatedSecureSecret: Data?
|
||||
if let encryptedSecret = secureSecret {
|
||||
flags |= 1 << 2
|
||||
if let decryptedSecret = decryptedSecureSecret(encryptedSecretData: encryptedSecret, password: currentPassword ?? "") {
|
||||
updatedSecureSecret = encryptedSecureSecret(secretData: decryptedSecret, password: password)
|
||||
} else {
|
||||
updatedSecureSecret = Data()
|
||||
}
|
||||
}
|
||||
|
||||
let updatedPasswordHash = sha256Digest(updatedData)
|
||||
return account.network.request(Api.functions.account.updatePasswordSettings(currentPasswordHash: currentPasswordHash, newSettings: Api.account.PasswordInputSettings.passwordInputSettings(flags: flags, newSalt: Buffer(data: nextSalt), newPasswordHash: Buffer(data: updatedPasswordHash), hint: hint, email: email, newSecureSecret: nil)), automaticFloodWait: false)
|
||||
return network.request(Api.functions.account.updatePasswordSettings(currentPasswordHash: currentPasswordHash, newSettings: Api.account.PasswordInputSettings.passwordInputSettings(flags: flags, newSalt: Buffer(data: nextSalt), newPasswordHash: Buffer(data: updatedPasswordHash), hint: hint, email: email, newSecureSecret: updatedSecureSecret.flatMap(Buffer.init))), automaticFloodWait: false)
|
||||
|> map { _ -> UpdateTwoStepVerificationPasswordResult in
|
||||
return .password(password: password, pendingEmailPattern: nil)
|
||||
}
|
||||
|> `catch` { error -> Signal<UpdateTwoStepVerificationPasswordResult, MTRpcError> in
|
||||
if error.errorDescription == "EMAIL_UNCONFIRMED" {
|
||||
return twoStepAuthData(account.network)
|
||||
return twoStepAuthData(network)
|
||||
|> map { result -> UpdateTwoStepVerificationPasswordResult in
|
||||
return .password(password: password, pendingEmailPattern: result.unconfirmedEmailPattern)
|
||||
}
|
||||
@@ -152,6 +176,41 @@ public func updateTwoStepVerificationPassword(account: Account, currentPassword:
|
||||
}
|
||||
}
|
||||
|
||||
enum UpdateTwoStepVerificationSecureSecretResult {
|
||||
case success
|
||||
}
|
||||
|
||||
enum UpdateTwoStepVerificationSecureSecretError {
|
||||
case generic
|
||||
}
|
||||
|
||||
func updateTwoStepVerificationSecureSecret(network: Network, password: String, updatedSecret: Data) -> Signal<UpdateTwoStepVerificationSecureSecretResult, UpdateTwoStepVerificationSecureSecretError> {
|
||||
return twoStepAuthData(network)
|
||||
|> mapError { _ -> UpdateTwoStepVerificationSecureSecretError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { authData -> Signal<UpdateTwoStepVerificationSecureSecretResult, UpdateTwoStepVerificationSecureSecretError> in
|
||||
guard let currentSalt = authData.currentSalt else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
var data = Data()
|
||||
data.append(currentSalt)
|
||||
data.append(password.data(using: .utf8, allowLossyConversion: true)!)
|
||||
data.append(currentSalt)
|
||||
let currentPasswordHash = Buffer(data: sha256Digest(data))
|
||||
|
||||
let flags: Int32 = (1 << 2)
|
||||
return network.request(Api.functions.account.updatePasswordSettings(currentPasswordHash: currentPasswordHash, newSettings: .passwordInputSettings(flags: flags, newSalt: nil, newPasswordHash: nil, hint: nil, email: nil, newSecureSecret: Buffer(data: updatedSecret))), automaticFloodWait: false)
|
||||
|> mapError { _ -> UpdateTwoStepVerificationSecureSecretError in
|
||||
return .generic
|
||||
}
|
||||
|> map { _ -> UpdateTwoStepVerificationSecureSecretResult in
|
||||
return .success
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func updateTwoStepVerificationEmail(account: Account, currentPassword: String, updatedEmail: String) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
|
||||
return twoStepAuthData(account.network)
|
||||
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
||||
|
||||
Reference in New Issue
Block a user