@@ -640,6 +640,16 @@ public async Task<IActionResult> DecryptToPqc2(Guid emailId)
640640 if ( TryParseEnvelope ( email . Subject , out var otpSubjectEnvelope ) )
641641 {
642642 pqcSubject = await DecryptOTPAsync ( otpSubjectEnvelope ) ;
643+ // Check if OTP decryption failed
644+ if ( pqcSubject == "OTP decryption failed" || pqcSubject == "Decryption failed" )
645+ {
646+ _logger . LogError ( "OTP decryption failed for subject" ) ;
647+ return BadRequest ( new {
648+ success = false ,
649+ message = "Failed to decrypt email: OTP decryption failed for subject" ,
650+ detail = "The OTP service may be unavailable or the encryption key may have expired"
651+ } ) ;
652+ }
643653 }
644654 else
645655 {
@@ -650,6 +660,16 @@ public async Task<IActionResult> DecryptToPqc2(Guid emailId)
650660 if ( TryParseEnvelope ( email . Body , out var otpBodyEnvelope ) )
651661 {
652662 pqcBody = await DecryptOTPAsync ( otpBodyEnvelope ) ;
663+ // Check if OTP decryption failed
664+ if ( pqcBody == "OTP decryption failed" || pqcBody == "Decryption failed" )
665+ {
666+ _logger . LogError ( "OTP decryption failed for body" ) ;
667+ return BadRequest ( new {
668+ success = false ,
669+ message = "Failed to decrypt email: OTP decryption failed for body" ,
670+ detail = "The OTP service may be unavailable or the encryption key may have expired"
671+ } ) ;
672+ }
653673 }
654674 else
655675 {
@@ -757,10 +777,19 @@ public async Task<IActionResult> DecryptToPqc(Guid emailId)
757777 // PHASE 1: Decrypt OTP layer (outermost)
758778 _logger . LogInformation ( "Decrypting OTP layer for subject and body" ) ;
759779 string aesSubject , aesBody ;
780+ bool subjectDecryptionFailed = false ;
781+ bool bodyDecryptionFailed = false ;
760782
761783 if ( TryParseEnvelope ( email . Subject , out var otpSubjectEnvelope ) )
762784 {
763785 aesSubject = await DecryptOTPAsync ( otpSubjectEnvelope ) ;
786+ // Check if OTP decryption failed
787+ if ( aesSubject == "OTP decryption failed" || aesSubject == "Decryption failed" )
788+ {
789+ _logger . LogWarning ( "OTP decryption failed for subject, using fallback message" ) ;
790+ aesSubject = "[Decryption Failed - OTP key may have expired]" ;
791+ subjectDecryptionFailed = true ;
792+ }
764793 }
765794 else
766795 {
@@ -771,38 +800,65 @@ public async Task<IActionResult> DecryptToPqc(Guid emailId)
771800 if ( TryParseEnvelope ( email . Body , out var otpBodyEnvelope ) )
772801 {
773802 aesBody = await DecryptOTPAsync ( otpBodyEnvelope ) ;
803+ // Check if OTP decryption failed
804+ if ( aesBody == "OTP decryption failed" || aesBody == "Decryption failed" )
805+ {
806+ _logger . LogWarning ( "OTP decryption failed for body, using fallback message" ) ;
807+ aesBody = "[Decryption Failed - OTP key may have expired. The encryption key for this message is no longer available.]" ;
808+ bodyDecryptionFailed = true ;
809+ }
774810 }
775811 else
776812 {
777813 _logger . LogWarning ( "Failed to parse OTP envelope for body" ) ;
778814 aesBody = email . Body ;
779815 }
780816
781- // PHASE 2: Decrypt AES layer (middle)
817+ // PHASE 2: Decrypt AES layer (middle) - skip if OTP decryption failed
782818 _logger . LogInformation ( "Decrypting AES layer for subject and body" ) ;
783819 string pqcSubject , pqcBody ;
784820
785- if ( TryParseAESEnvelope ( aesSubject , out var aesSubjectEnvelope ) )
821+ if ( ! subjectDecryptionFailed && TryParseAESEnvelope ( aesSubject , out var aesSubjectEnvelope ) )
786822 {
787823 pqcSubject = await DecryptAESAsync ( aesSubjectEnvelope ) ;
824+ // Check if AES decryption failed
825+ if ( pqcSubject . StartsWith ( "AES decryption failed" ) )
826+ {
827+ _logger . LogWarning ( "AES decryption failed for subject, using fallback message" ) ;
828+ pqcSubject = "[Decryption Failed - AES decryption error]" ;
829+ subjectDecryptionFailed = true ;
830+ }
788831 }
789832 else
790833 {
791- _logger . LogWarning ( "Failed to parse AES envelope for subject" ) ;
834+ if ( ! subjectDecryptionFailed )
835+ {
836+ _logger . LogWarning ( "Failed to parse AES envelope for subject" ) ;
837+ }
792838 pqcSubject = aesSubject ;
793839 }
794840
795- if ( TryParseAESEnvelope ( aesBody , out var aesBodyEnvelope ) )
841+ if ( ! bodyDecryptionFailed && TryParseAESEnvelope ( aesBody , out var aesBodyEnvelope ) )
796842 {
797843 pqcBody = await DecryptAESAsync ( aesBodyEnvelope ) ;
844+ // Check if AES decryption failed
845+ if ( pqcBody . StartsWith ( "AES decryption failed" ) )
846+ {
847+ _logger . LogWarning ( "AES decryption failed for body, using fallback message" ) ;
848+ pqcBody = "[Decryption Failed - AES decryption error. The encryption key for this message is no longer available.]" ;
849+ bodyDecryptionFailed = true ;
850+ }
798851 }
799852 else
800853 {
801- _logger . LogWarning ( "Failed to parse AES envelope for body" ) ;
854+ if ( ! bodyDecryptionFailed )
855+ {
856+ _logger . LogWarning ( "Failed to parse AES envelope for body" ) ;
857+ }
802858 pqcBody = aesBody ;
803859 }
804860
805- // PHASE 3: Decrypt attachments from OTP+AES layers to PQC layer
861+ // PHASE 3: Decrypt attachments from OTP+AES layers to PQC layer - continue even if some fail
806862 _logger . LogInformation ( "Decrypting attachments for PQC_3_LAYER email" ) ;
807863 string ? pqcAttachmentsJson = null ;
808864 if ( ! string . IsNullOrWhiteSpace ( email . Attachments ) )
@@ -813,29 +869,64 @@ public async Task<IActionResult> DecryptToPqc(Guid emailId)
813869 if ( attachmentsList != null && attachmentsList . Count > 0 )
814870 {
815871 var decryptedAttachments = new List < object > ( ) ;
816- foreach ( var item in attachmentsList )
872+ for ( int idx = 0 ; idx < attachmentsList . Count ; idx ++ )
817873 {
818- var fileName = item . ContainsKey ( "fileName" ) ? item [ "fileName" ] ? . ToString ( ) : null ;
819- var contentType = item . ContainsKey ( "contentType" ) ? item [ "contentType" ] ? . ToString ( ) : null ;
820- var envelope = item . ContainsKey ( "envelope" ) ? item [ "envelope" ] ? . ToString ( ) : null ;
821-
822- if ( ! string . IsNullOrWhiteSpace ( fileName ) && ! string . IsNullOrWhiteSpace ( envelope ) )
874+ try
823875 {
824- // Decrypt OTP layer first
825- if ( TryParseEnvelope ( envelope , out var otpEnvelope ) )
876+ var item = attachmentsList [ idx ] ;
877+ var fileName = item . ContainsKey ( "fileName" ) ? item [ "fileName" ] ? . ToString ( ) : null ;
878+ var contentType = item . ContainsKey ( "contentType" ) ? item [ "contentType" ] ? . ToString ( ) : null ;
879+ var envelope = item . ContainsKey ( "envelope" ) ? item [ "envelope" ] ? . ToString ( ) : null ;
880+
881+ if ( ! string . IsNullOrWhiteSpace ( fileName ) && ! string . IsNullOrWhiteSpace ( envelope ) )
826882 {
827- var aesEnvelope = await DecryptOTPAsync ( otpEnvelope ) ;
883+ _logger . LogInformation ( "Processing attachment {Index}: {FileName}" , idx , fileName ) ;
828884
829- // Then decrypt AES layer to get PQC envelope
830- if ( TryParseAESEnvelope ( aesEnvelope , out var aesEnvelopeObj ) )
885+ // Decrypt OTP layer first
886+ if ( TryParseEnvelope ( envelope , out var otpEnvelope ) )
831887 {
832- var pqcEnvelope = await DecryptAESAsync ( aesEnvelopeObj ) ;
833- decryptedAttachments . Add ( new { fileName , contentType , pqcEnvelope } ) ;
888+ var aesEnvelope = await DecryptOTPAsync ( otpEnvelope ) ;
889+
890+ // Check if OTP decryption failed
891+ if ( aesEnvelope == "OTP decryption failed" || aesEnvelope == "Decryption failed" )
892+ {
893+ _logger . LogWarning ( "OTP decryption failed for attachment {Index}: {FileName}, skipping" , idx , fileName ) ;
894+ continue ;
895+ }
896+
897+ // Then decrypt AES layer to get PQC envelope
898+ if ( TryParseAESEnvelope ( aesEnvelope , out var aesEnvelopeObj ) )
899+ {
900+ var pqcEnvelope = await DecryptAESAsync ( aesEnvelopeObj ) ;
901+
902+ // Check if AES decryption failed
903+ if ( pqcEnvelope . StartsWith ( "AES decryption failed" ) )
904+ {
905+ _logger . LogWarning ( "AES decryption failed for attachment {Index}: {FileName}, skipping" , idx , fileName ) ;
906+ continue ;
907+ }
908+
909+ decryptedAttachments . Add ( new { fileName , contentType , pqcEnvelope } ) ;
910+ _logger . LogInformation ( "Successfully decrypted attachment {Index}: {FileName}" , idx , fileName ) ;
911+ }
912+ else
913+ {
914+ _logger . LogWarning ( "Failed to parse AES envelope for attachment {Index}: {FileName}" , idx , fileName ) ;
915+ }
916+ }
917+ else
918+ {
919+ _logger . LogWarning ( "Failed to parse OTP envelope for attachment {Index}: {FileName}" , idx , fileName ) ;
834920 }
835921 }
836922 }
923+ catch ( Exception attEx )
924+ {
925+ _logger . LogError ( attEx , "Failed to decrypt individual attachment {Index}, continuing with others" , idx ) ;
926+ }
837927 }
838928 pqcAttachmentsJson = JsonSerializer . Serialize ( decryptedAttachments , _jsonOptions ) ;
929+ _logger . LogInformation ( "Successfully decrypted {Count} out of {Total} attachments" , decryptedAttachments . Count , attachmentsList . Count ) ;
839930 }
840931 }
841932 catch ( Exception ex )
0 commit comments