//
//	PDF Structure
//	Verify sample code
//
/*
Copyright(c) 2026 株式会社トラスト・ソフトウェア・システム, All Rights Reserved.
*/

using System;
using System.Security.Cryptography.X509Certificates;
using PDFTools.PdfStructure;
using PDFTools.PdfStructure.Security;
using PDFTools.PdfStructure.Security.Misc;

namespace VerifyTest
{
	class Verify
	{
		static void Main(string[] args)
		{
			using (var stc = new Structure(""))
			{
				stc.OpenDoc("../../../../../resources/hello Signed.pdf");

				//Security Interface
				using (var sec = stc.GetSecurityInterface())
				{
					//PDF文書のバージョンに由来する階層データ
					DocumentHierarcyInfo[] v;
					try
					{
						v = sec.GetHierarcyInformation();
					}
					catch (Exception e)
					{
						Console.WriteLine($"エラー：{e.Message}");
						goto end_proc;
					}

					//階層データ出力
					for (int i = 0; i < v.Length; i++)
					{
						Console.WriteLine($"Version[{i}]");
						Console.WriteLine($"\tFileSize(elm): {v[i].FileSize}");
						if (v[i].has_page_elm > 0) Console.WriteLine("\tElement has \"Page Object(s)\"");
						if (v[i].has_resource_elm > 0) Console.WriteLine("\tElement has \"Resources Objext(s)\"");
						if (v[i].has_annotation_elm > 0) Console.WriteLine("\tElement has \"Annotation Objext(s)\"");

						if (v[i].has_DSS > 0) Console.WriteLine("\thas DSS dictionary");
						if (v[i].has_VRI > 0)
						{
							Console.WriteLine("\thas VRI dictionary");
							if (v[i].VRI_Certs.Length > 0) Console.WriteLine($"\t\tnumber of Certs: {v[i].VRI_Certs.Length}");
							if (v[i].VRI_CRLs.Length > 0) Console.WriteLine($"\t\tnumber of CRGs: {v[i].VRI_CRLs.Length}");
							if (v[i].VRI_OCSPs.Length > 0) Console.WriteLine($"\t\tnumber of CRGs: {v[i].VRI_OCSPs.Length}");
						}

						if (true)
						{
							//電子署名
							if (v[i].has_SIG > 0 || v[i].has_DTS > 0)
							{
								if (v[i].has_SIG > 0) Console.WriteLine("\thas Signature{0}", v[i].has_SIG == 3 ? " w/\"Timestamp\"" : "");
								if (v[i].has_DTS > 0) Console.WriteLine("\tSignature is Timestamp");
								if (v[i].sig_verified > 0)
									Console.WriteLine("\tThe signatute is validate.");
								else
									Console.WriteLine("\tThe signatute is INVALIDATE.");
							}
							//署名時刻
							if (v[i].SigningTime.Ticks > 1)
							{
								Console.Write($"\tSigning Time: {v[i].SigningTime.ToString()} - ");
								switch (v[i].SigningTime_source)
								{
									case SecKindOfSigningTime.SEC_SIGNING_TIME_SYS:
										Console.WriteLine("現在のシステムの時刻");
										break;
									case SecKindOfSigningTime.SEC_SIGNING_TIME_M:
										Console.WriteLine("署名辞書に記載された時刻");
										break;
									case SecKindOfSigningTime.SEC_SIGNING_TIME_SIGN:
										Console.WriteLine("署名メッセージに記載された時刻");
										break;
									case SecKindOfSigningTime.SEC_SIGNING_TIME_TS:
										Console.WriteLine("タイムスタンプの時刻");
										break;
									default:
										Console.WriteLine();
										break;
								}
							}

							//タイムスタンプ
							if (v[i].has_DTS > 0 || v[i].has_SIG == 3)
							{
								Console.WriteLine("\tTimeStamp Information{0}", v[i].has_DTS > 0 ? "" : " (タイムスタンプは副署名)");
								Console.WriteLine($"\t\tTSA PolicyId: {v[i].TstPolicyId}");
								Console.WriteLine($"\t\tHash OID: {v[i].HashOid}");
								Console.WriteLine("\t\tHash Message: {0}", v[i].hash_is_matched_ts > 0 ? "The hash value is matched" : "Invalid hash Value");
#if false
								Console.WriteLine(BitConverter.ToString(v[i].HashMessage).Replace("-",string.Empty));
#elif true
								Console.WriteLine(Utility.BinaryToString(v[i].HashMessage, Utility.CryptStringFlag.CRYPT_STRING_HEXASCIIADDR));
#endif
								Console.WriteLine("\t\tSerialNumber: {0}", BitConverter.ToString(v[i].TstSn).Replace("-", string.Empty));
								Console.WriteLine($"\t\tGenTime: {v[i].GenTime}");
								Console.WriteLine($"\t\tGenTime(ascii:JST): {v[i].GenTm.ToString()}");
								Console.Write("\t\tAccuracy: ");
								if (v[i].AccuacySec >= 0) Console.Write($" Seconds={v[i].AccuacySec}");
								if (v[i].AccuacyMilli >= 0) Console.Write($" Millis={v[i].AccuacyMilli}");
								if (v[i].AccuacyMicro >= 0) Console.Write($" Micros={v[i].AccuacyMicro}");
								Console.WriteLine();
								Console.WriteLine($"\t\tTSA Name: {v[i].TsaName}");
							}
						}

						//署名データ
						if (v[i].has_SIG > 0 || v[i].has_DTS > 0)
						{
							Console.WriteLine($"\tSigned File Size: {v[i].SignedFileSize}");
							Console.WriteLine($"\tByteRange: [ {v[i].ByteRange[0]} {v[i].ByteRange[1]} {v[i].ByteRange[2]} {v[i].ByteRange[3]} ]");
							Console.WriteLine($"\tTite: {v[i].Title}");
							Console.WriteLine($"\tName: {v[i].Name}");
							Console.WriteLine($"\tM: {v[i].M}");
							Console.WriteLine($"\tFilter: {v[i].Filter}");
							Console.WriteLine($"\tSubFilter: {v[i].SubFilter}");
							Console.WriteLine($"\tSigner DigestAlgorithm: {v[i].DigestAlgorithm}");
							//ハッシュ値
							switch (v[i].has_SIG)
							{
								case 3:
									Console.WriteLine("\tThe Signature Hash Value is {0}matched.", v[i].hash_is_matched_sign > 0 ? "" : "not ");
									Console.WriteLine("\tThe Timestamp Hash Value is {0}matched.", v[i].hash_is_matched_ts > 0 ? "" : "not ");
									break;
								case 2:
									Console.WriteLine("\tThe Signature Hash Value is {0}matched.", v[i].hash_is_matched_sign > 0 ? "" : "not ");
									break;
								case 1:
									Console.WriteLine("\tThe Timestamp Hash Value is {0}matched.", v[i].hash_is_matched_ts > 0 ? "" : "not ");
									break;
							}

#if false
							Console.WriteLine($"\tProp_Build: {v[i].PropBuild}");
							Console.WriteLine($"\tSignatureObject: {v[i].SigObj}");
#endif

							//署名者証明書
							if (v[i].SignerCert != null)
							{
#if false
								var cert = new X509Certificate2(v[i].SignerCert);
#elif false
								Utility.ViewCertificate(v[i].SignerCert);
#endif
								Console.WriteLine("\tSigner Certificate Information");
								//発行者
								Console.WriteLine($"\t\tIssuer: {new X500DistinguishedName(v[i].IssuerName).Name}");
								//サブジェクト名
								Console.WriteLine($"\t\tSubject: {new X500DistinguishedName(v[i].SignerCertSubj).Name}");
								//シリアル番号
								Console.WriteLine($"\t\tSerialNumber: {BitConverter.ToString(v[i].SignerCertSn).Replace("-", string.Empty)}");
								//証明書の署名アルゴリズム
								Console.WriteLine($"\t\tSignatuteAlgotithmID: {v[i].SignatureAlgorithmId}");
							}
						}

						//失効情報
#if true
						if (v[i].cms_CRLs != null && v[i].cms_CRLs.Length > 0)
						{
							for (int j = 0; j < v[i].cms_CRLs.Length; j++)
								Utility.ViewCRL(v[i].cms_CRLs[j]);
						}
						if (v[i].cms_OCSPs != null && v[i].cms_OCSPs.Length > 0)
						{
							for (int j = 0; j < v[i].cms_OCSPs.Length; j++)
							{
								Console.WriteLine($"OCSP#{j+1}:");
								Console.WriteLine(Utility.BinaryToString(v[i].cms_OCSPs[j], Utility.CryptStringFlag.CRYPT_STRING_HEXASCIIADDR));
							}
						}
#endif
					}
				}
			}

end_proc:
			Environment.Exit(0);
		}
	}
}
