Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Modules/CryptoLib/Sources/CryptoObjC/include/Decrypt.mm
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ - (instancetype)initWithLabel:(const std::string &)label pub:(NSData*)pub concat
NSDate *validTo = nil;
if (info.contains("server_exp")) {
long long epochTime = [[NSString stringWithStdString:info["server_exp"]] longLongValue];
validTo = [NSDate dateWithTimeIntervalSince1970:epochTime];
if (epochTime > 0) {
validTo = [NSDate dateWithTimeIntervalSince1970:epochTime];
}
}

if (self = [self initWithCnVal:cn serialNumber:serial certType:certTypeFromLabel(type) validTo:validTo data:pub concatKDFAlgorithmURI:concatKDFAlgorithmURI lockLabel:@"" lockType:@""]) {
Expand Down
1 change: 1 addition & 0 deletions RIADigiDoc.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
DI/AppContainer.swift,
Domain/Model/BottomSheetButton.swift,
Domain/Model/CertificateExtensionData.swift,
Domain/Model/Crypto/RecipientDecryptionStatus.swift,
Domain/Model/DependencyLicense.swift,
Domain/Model/EncryptionCdocOption.swift,
Domain/Model/EncryptionServerInfo.swift,
Expand Down
71 changes: 71 additions & 0 deletions RIADigiDoc/Domain/Model/Crypto/RecipientDecryptionStatus.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright 2017 - 2026 Riigi Infosüsteemi Amet
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

import Foundation

public enum RecipientDecryptionStatus: Sendable {
case notEncrypted
case notEncryptedExpired
case expired
case valid

public static func resolve(
validTo: Date?,
isCDOC2Container: Bool,
isEncryptedOrDecrypted: Bool,
now: Date = Date()
) -> RecipientDecryptionStatus? {
guard isCDOC2Container, let validTo else { return nil }

let isExpired = validTo < now

switch (isEncryptedOrDecrypted, isExpired) {
case (false, true): return .notEncryptedExpired
case (false, false): return .notEncrypted
case (true, true): return .expired
case (true, false): return .valid
}
}

public static func allExpiredDate(
validTos: [Date?],
isCDOC2Container: Bool,
now: Date = Date()
) -> Date? {
guard isCDOC2Container, !validTos.isEmpty else { return nil }

guard validTos.allSatisfy({ validTo in
guard let validTo else { return false }
return validTo < now
}) else {
return nil
}

return validTos.compactMap { $0 }.max()
}

public var localizationKey: String {
switch self {
case .notEncrypted: return "Expires on"
case .notEncryptedExpired: return "Expired on"
case .expired: return "Decryption expired"
case .valid: return "Decryption until"
}
}
}
108 changes: 108 additions & 0 deletions RIADigiDoc/Supporting files/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -1493,6 +1493,24 @@
}
}
},
"Crypto container must be decrypted" : {
"comment" : "Crypto container files placeholder when contents cannot be listed",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The container must be decrypted in order to see the contents of an encrypted container."
}
},
"et" : {
"stringUnit" : {
"state" : "translated",
"value" : "Krüpteeritud ümbriku sisu nägemiseks tuleb ümbrik dekrüpteerida."
}
}
}
},
"Crypto files encrypted" : {
"comment" : "Crypto container files names locked",
"extractionState" : "manual",
Expand Down Expand Up @@ -1817,6 +1835,42 @@
}
}
},
"Decryption expired" : {
"comment" : "CDOC2 recipient decryption expired badge",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Decryption expired %@"
}
},
"et" : {
"stringUnit" : {
"state" : "translated",
"value" : "Dekrüpteerimise võimalus aegus %@"
}
}
}
},
"Decryption until" : {
"comment" : "CDOC2 recipient decryption valid until badge",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Decryption until %@"
}
},
"et" : {
"stringUnit" : {
"state" : "translated",
"value" : "Dekrüpteerimine võimalik kuni %@"
}
}
}
},
"Decryption method" : {
"comment" : "Title for signing method in container decrypt view",
"extractionState" : "manual",
Expand Down Expand Up @@ -2015,6 +2069,24 @@
}
}
},
"Encrypted files" : {
"comment" : "Crypto container files tab title",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Encrypted files"
}
},
"et" : {
"stringUnit" : {
"state" : "translated",
"value" : "Krüpteeritud failid"
}
}
}
},
"Encrypt" : {
"comment" : "Encrypt button",
"extractionState" : "manual",
Expand Down Expand Up @@ -2249,6 +2321,42 @@
}
}
},
"Expired on" : {
"comment" : "CDOC2 recipient certificate expired badge",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Expired on %@"
}
},
"et" : {
"stringUnit" : {
"state" : "translated",
"value" : "Aegus %@"
}
}
}
},
"Expires on" : {
"comment" : "CDOC2 recipient certificate expiry badge",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Expires on %@"
}
},
"et" : {
"stringUnit" : {
"state" : "translated",
"value" : "Aegub %@"
}
}
}
},
"Extend" : {
"comment" : "Confirm button label in extend signatures dialog",
"extractionState" : "manual",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ struct CryptoDataFilesLockedSection: View {
@AppTheme private var theme
@AppTypography private var typography

var isDecryptionUnavailable = false

private var message: String {
isDecryptionUnavailable
? languageSettings.localized("Crypto container must be decrypted")
: languageSettings.localized("Crypto files encrypted")
}

var body: some View {
VStack {
HStack {
Expand All @@ -37,15 +45,15 @@ struct CryptoDataFilesLockedSection: View {
.padding(.trailing, Dimensions.Padding.SPadding)
.accessibilityHidden(true)

Text(verbatim: languageSettings.localized("Crypto files encrypted"))
Text(verbatim: message)
.font(typography.bodyMedium)
.fixedSize(horizontal: false, vertical: true)
.lineLimit(nil)
.minimumScaleFactor(0.5)
.multilineTextAlignment(TextAlignment.leading)
.accessibilityLabel(
Text(
verbatim: languageSettings.localized("Crypto files encrypted").lowercased()
verbatim: message.lowercased()
)
)

Expand Down
12 changes: 10 additions & 2 deletions RIADigiDoc/UI/Component/Container/Crypto/EncryptView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ struct EncryptView: View {
languageSettings.localized("Container files")
}

private var containerEncryptedFilesTitle: String {
languageSettings.localized("Encrypted files")
}

private var shareTitle: String {
languageSettings.localized("Share")
}
Expand Down Expand Up @@ -338,7 +342,7 @@ struct EncryptView: View {
.padding(.vertical, Dimensions.Padding.MPadding)
} else {
TabView(selectedTab: $selectedTab, titles: [
containerFilesTitle,
containerEncryptedFilesTitle,
containerRecipientsTitle
]) {
if selectedTab == .files {
Expand All @@ -358,14 +362,18 @@ struct EncryptView: View {
$viewModel.navigateToNestedSignedContainerView
)
} else {
CryptoDataFilesLockedSection()
CryptoDataFilesLockedSection(
isDecryptionUnavailable: viewModel.isDecryptionUnavailable
)
.environment(languageSettings)
}
} else {
RecipientsListView(
recipients: viewModel.recipients,
selectedRecipient: $selectedRecipient,
showRemoveRecipientButton: viewModel.isRecipientRemoveButtonShown(),
isCDOC2Container: viewModel.isContainerCDOC2,
isEncryptedOrDecrypted: viewModel.isContainerEncryptedOrDecrypted,
showRemoveRecipientModal: $showRemoveRecipientModal,
nameUtil: nameUtil,
recipientUtil: recipientUtil
Expand Down
24 changes: 23 additions & 1 deletion RIADigiDoc/UI/Component/Container/Crypto/RecipientView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ struct RecipientView: View {
let recipientUtil: RecipientUtilProtocol
let showMoreOptionsButton: Bool
var showRemoveRecipientButton: Bool
let isCDOC2Container: Bool
let isEncryptedOrDecrypted: Bool
@Binding var showRemoveRecipientModal: Bool
var onSelect: (() -> Void)?

Expand Down Expand Up @@ -103,6 +105,14 @@ struct RecipientView: View {
).date
}

var decryptionStatus: RecipientDecryptionStatus? {
RecipientDecryptionStatus.resolve(
validTo: recipient.validTo,
isCDOC2Container: isCDOC2Container,
isEncryptedOrDecrypted: isEncryptedOrDecrypted
)
}

init(
recipientIndex: Int,
recipient: Addressee,
Expand All @@ -111,6 +121,8 @@ struct RecipientView: View {
recipientUtil: RecipientUtilProtocol = Container.shared.recipientUtil(),
showMoreOptionsButton: Bool = true,
showRemoveRecipientButton: Bool = true,
isCDOC2Container: Bool = false,
isEncryptedOrDecrypted: Bool = false,
showRemoveRecipientModal: Binding<Bool>,
onSelect: (() -> Void)? = nil
) {
Expand All @@ -120,6 +132,8 @@ struct RecipientView: View {
self.recipientUtil = recipientUtil
self.showMoreOptionsButton = showMoreOptionsButton
self.showRemoveRecipientButton = showRemoveRecipientButton
self.isCDOC2Container = isCDOC2Container
self.isEncryptedOrDecrypted = isEncryptedOrDecrypted
self._showRemoveRecipientModal = showRemoveRecipientModal
self.onSelect = onSelect
}
Expand Down Expand Up @@ -149,7 +163,8 @@ struct RecipientView: View {
)

let certType = recipientUtil.getRecipientCertTypeText(certType: recipient.certType)
let validPart = (validToDate.isEmpty || isPasswordRecipient)
let status = decryptionStatus
let validPart = (validToDate.isEmpty || isPasswordRecipient || status != nil)
? ""
: " " + languageSettings.localized("Valid to", [validToDate])

Expand All @@ -158,6 +173,13 @@ struct RecipientView: View {
.foregroundStyle(theme.onSurfaceVariant)
.fixedSize(horizontal: false, vertical: true)
.multilineTextAlignment(.leading)

if let status {
ColoredRecipientStatusText(
text: languageSettings.localized(status.localizationKey, [validToDate]),
status: status
)
}
}
.accessibilityElement(children: .combine)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ struct RecipientsListView: View {
let recipients: [Addressee]
@Binding var selectedRecipient: Addressee?
var showRemoveRecipientButton: Bool
var isCDOC2Container: Bool = false
var isEncryptedOrDecrypted: Bool = false
@Binding var showRemoveRecipientModal: Bool

let nameUtil: NameUtilProtocol
Expand All @@ -44,6 +46,8 @@ struct RecipientsListView: View {
nameUtil: nameUtil,
recipientUtil: recipientUtil,
showRemoveRecipientButton: showRemoveRecipientButton,
isCDOC2Container: isCDOC2Container,
isEncryptedOrDecrypted: isEncryptedOrDecrypted,
showRemoveRecipientModal: $showRemoveRecipientModal,
onSelect: {
selectedRecipient = recipient
Expand All @@ -59,6 +63,8 @@ struct RecipientsListView: View {
nameUtil: nameUtil,
recipientUtil: recipientUtil,
showRemoveRecipientButton: showRemoveRecipientButton,
isCDOC2Container: isCDOC2Container,
isEncryptedOrDecrypted: isEncryptedOrDecrypted,
showRemoveRecipientModal: $showRemoveRecipientModal,
onSelect: {
selectedRecipient = recipient
Expand Down
Loading
Loading