public void Java2NetUnaddressed() { RunJava("be.smals.ehealth.etee.crypto.examples.SealForUnknown"); UnsealResult result; SecretKey kek = new SecretKey(Convert.FromBase64String("btSefztkXjZmlZyHQIumLA=="), Convert.FromBase64String("aaUnRynIwd3GFQmhXfW+VQ==")); FileStream fs = new FileStream("message_from_alice_for_unknown.msg", FileMode.Open); using(fs) { result = anonUnsealer.Unseal(fs, kek); } System.Console.WriteLine(result.SecurityInformation); Assert.AreEqual(Egelke.EHealth.Etee.Crypto.Status.TrustStatus.None, result.SecurityInformation.TrustStatus); Assert.AreEqual(2, result.SecurityInformation.OuterSignature.Subject.SecurityViolations.Count); //v1.6 does not add the chain of certificates, only the leaf Assert.IsTrue(result.SecurityInformation.OuterSignature.Subject.SecurityViolations.Contains(CertSecurityViolation.IssuerTrustUnknown)); //Old bob and alice don't have the right key usage Assert.IsTrue(result.SecurityInformation.OuterSignature.Subject.SecurityViolations.Contains(CertSecurityViolation.NotValidForUsage)); Assert.AreEqual(ValidationStatus.Valid, result.SecurityInformation.ValidationStatus); Assert.IsTrue(result.AuthenticationCertificate.Subject.Contains("NIHII=00000000101")); byte[] bytes = new byte[result.UnsealedData.Length]; result.UnsealedData.Read(bytes, 0, bytes.Length); String msg = Encoding.UTF8.GetString(bytes); Assert.IsTrue(msg.StartsWith("This is a secret message from Alice for an unknown addressee written at ")); }
private Stream Seal(ITempStreamFactory factory, Stream unsealedStream, SecretKey key, X509Certificate2[] certs) { trace.TraceEvent(TraceEventType.Information, 0, "Sealing message of {0} bytes for {1} known recipients and {2} unknown recipients to level {3}", unsealedStream.Length, certs.Length, key == null ? 0 : 1, this.level); //Create inner signed stream Stream signed = factory.CreateNew(); using (signed) { //Inner sign Stream intermedate = factory.CreateNew(); using (intermedate) { if (signature == null) { Sign(signed, unsealedStream, authentication); signed.Position = 0; signed.CopyTo(intermedate); } else { Sign(signed, unsealedStream, signature); signed.Position = 0; //Add the certificate and revocation info only (no time-stamp) TimemarkKey timemarkKey; Complete(this.level & ~Level.T_Level, intermedate, signed, signature, out timemarkKey); } intermedate.Position = 0; //Create encrypted stream Stream signedEncrypted = factory.CreateNew(); using (signedEncrypted) { //Encrypt Encrypt(signedEncrypted, intermedate, certs, key); //Outer sign with retry for eID int tries = 0; bool success = false; Stream sealedStream = null; while (!success) { signedEncrypted.Position = 0; try { //This is the output, so we need to make it a temp stream (temp file or memory stream) sealedStream = factory.CreateNew(); Sign(sealedStream, signedEncrypted, authentication); success = true; } catch (CryptographicException ce) { //Keep track trace.TraceEvent(TraceEventType.Warning, 0, "Failed to put outer signature (try {0}): {1}", tries, ce); if (tries++ < 4) { sealedStream.Close(); sealedStream = null; Thread.Sleep((int)Math.Pow(10, tries)); //wait longer and longer } else { sealedStream.Close(); throw ce; } } } try { sealedStream.Position = 0; //reset the stream //Complete the outer signature with revocation info & time-stamp if needed TimemarkKey timemarkKey; Stream completedStream = factory.CreateNew(); Complete(this.level, completedStream, sealedStream, authentication, out timemarkKey); completedStream.Position = 0; //reset the stream return completedStream; } finally { sealedStream.Close(); } } } } }
public void Net2JavaUnaddressed() { String text = "This is a secret message from Alice for an unknown addressee written at " + DateTime.Now.ToString(); SecretKey kek = new SecretKey(Convert.FromBase64String("btSefztkXjZmlZyHQIumLA=="), Convert.FromBase64String("aaUnRynIwd3GFQmhXfW+VQ==")); Stream msg = aliceSealer.Seal(new MemoryStream(Encoding.UTF8.GetBytes(text)), kek); FileStream msgFile = new FileStream("message_from_alice_for_unknown.msg", FileMode.OpenOrCreate); msg.CopyTo(msgFile); String output = RunJava("be.smals.ehealth.etee.crypto.examples.UnsealByUnknown"); Assert.IsTrue(output.Contains("NIHII=00000000101")); Assert.IsTrue(output.Contains(text)); }
public Stream Seal(Stream unsealed, SecretKey key, params EncryptionToken[] tokens) { ITempStreamFactory factory = NewFactory(unsealed); return Seal(factory, unsealed, key, ConverToX509Certificates(tokens)); }
protected void Encrypt(Stream cipher, Stream clear, ICollection<X509Certificate2> certs, SecretKey key) { trace.TraceEvent(TraceEventType.Information, 0, "Encrypting message for {0} known and {1} unknown recipient", certs == null ? 0 : certs.Count, key == null ? 0 : 1); CmsEnvelopedDataStreamGenerator encryptGenerator = new CmsEnvelopedDataStreamGenerator(); if (certs != null) { foreach (X509Certificate2 cert in certs) { BC::X509.X509Certificate bcCert = DotNetUtilities.FromX509Certificate(cert); encryptGenerator.AddKeyTransRecipient(bcCert); trace.TraceEvent(TraceEventType.Verbose, 0, "Added known recipient: {0}", bcCert.SubjectDN.ToString()); } } if (key != null) { encryptGenerator.AddKekRecipient("AES", key.BCKey, key.Id); trace.TraceEvent(TraceEventType.Verbose, 0, "Added unknown recipient [Algorithm={0}, keyId={1}]", "AES", key.IdString); } Stream encryptingStream = encryptGenerator.Open(cipher, EteeActiveConfig.Seal.EncryptionAlgorithm.Value); trace.TraceEvent(TraceEventType.Verbose, 0, "Create encrypted message (still empty) [EncAlgo={0} ({1})]", EteeActiveConfig.Seal.EncryptionAlgorithm.FriendlyName, EteeActiveConfig.Seal.EncryptionAlgorithm.Value); try { clear.CopyTo(encryptingStream); trace.TraceEvent(TraceEventType.Verbose, 0, "Message encrypted"); } finally { encryptingStream.Close(); trace.TraceEvent(TraceEventType.Verbose, 0, "Recipient infos added"); } }
private Stream Seal(ITempStreamFactory factory, Stream unsealedStream, SecretKey skey, X509Certificate2[] certs, WebKey[] webKeys) { #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Information, 0, "Sealing message of {0} bytes for {1}/{2} known recipients and {3} unknown recipients to level {3}", unsealedStream.Length, certs?.Length, webKeys?.Length, skey == null ? 0 : 1, this.level); #else logger.LogInformation("Sealing message of {0} bytes for {1}/{2} known recipients and {3} unknown recipients to level {3}", unsealedStream.Length, certs?.Length, webKeys?.Length, skey == null ? 0 : 1, this.level); #endif using ( Stream innerDetached = new MemoryStream(), innerEmbedded = factory.CreateNew(), encrypted = factory.CreateNew(), outerDetached = new MemoryStream() ) { TimemarkKey timemarkKey; //Inner sign if (signature != null) { SignDetached(innerDetached, unsealedStream, signature); } else if (ownWebKey != null) { SignDetached(innerDetached, unsealedStream, ownWebKey.BCKeyPair, ownWebKey.Id); } else { throw new InvalidOperationException("Tripple wrapper must have either cert of keypair for signing"); } //prepare to merge the detached inner signature with its content innerDetached.Position = 0; unsealedStream.Position = 0; //embed the content in the inner signature and add any required info if it uses a different cert. Complete(signature == authentication ? (Level?)null : this.level & ~Level.T_Level, innerEmbedded, innerDetached, unsealedStream, signature, out timemarkKey); //prepare to encrypt innerEmbedded.Position = 0; //Encrypt Encrypt(encrypted, innerEmbedded, certs, skey, webKeys); //Loop, since eID doesn't like to be use in very short succession int retry = 0; bool success = false; while (!success) { //prepare to create the outer signature encrypted.Position = 0; outerDetached.SetLength(0); try { //Create the outer signature if (signature != null) { SignDetached(outerDetached, encrypted, authentication); } else { SignDetached(outerDetached, encrypted, ownWebKey.BCKeyPair, ownWebKey.Id); } success = true; } catch (CryptographicException ce) { if (retry++ < 4) { #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Warning, 0, "Failed to put outer signature, staring loop: {0}", ce); #else logger.LogWarning("Failed to put outer signature, staring loop: {0}", ce); #endif System.Threading.Thread.Sleep((int)Math.Pow(10, retry)); } else { throw ce; } } } //prepare to merge the detached inner signature with its content encrypted.Position = 0; outerDetached.Position = 0; //embed the content in the out signature and add any required info Stream result = factory.CreateNew(); Complete(this.level, result, outerDetached, encrypted, authentication, out timemarkKey); //prepare to return the triple wrapped message result.Position = 0; //return the triple wrapped message return(result); } }
protected void Encrypt(Stream cipher, Stream clear, ICollection <X509Certificate2> certs, SecretKey key, WebKey[] webKeys) { #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Information, 0, "Encrypting message for {0} known and {1} unknown recipient", certs == null ? 0 : certs.Count, key == null ? 0 : 1); #else logger.LogInformation("Encrypting message for {0} known and {1} unknown recipient", certs == null ? 0 : certs.Count, key == null ? 0 : 1); #endif CmsEnvelopedDataStreamGenerator encryptGenerator = new CmsEnvelopedDataStreamGenerator(); if (certs != null) { foreach (X509Certificate2 cert in certs) { BC::X509.X509Certificate bcCert = DotNetUtilities.FromX509Certificate(cert); encryptGenerator.AddKeyTransRecipient(bcCert); #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Verbose, 0, "Added known recipient: {0} ({1})", bcCert.SubjectDN.ToString(), bcCert.IssuerDN.ToString()); #else logger.LogDebug("Added known recipient: {0} ({1})", bcCert.SubjectDN.ToString(), bcCert.IssuerDN.ToString()); #endif } } if (key != null) { encryptGenerator.AddKekRecipient("AES", key.BCKey, key.Id); #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Verbose, 0, "Added unknown recipient [Algorithm={0}, keyId={1}]", "AES", key.IdString); #else logger.LogDebug("Added unknown recipient [Algorithm={0}, keyId={1}]", "AES", key.IdString); #endif } if (webKeys != null) { foreach (WebKey webKey in webKeys) { encryptGenerator.AddKeyTransRecipient(webKey.BCPublicKey, webKey.Id); #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Verbose, 0, "Added web recipient [Algorithm={0}, keyId={1}]", "RSA", webKey.IdString); #else logger.LogDebug("Added web recipient [Algorithm={0}, keyId={1}]", "RSA", webKey.IdString); #endif } } Stream encryptingStream = encryptGenerator.Open(cipher, EteeActiveConfig.Seal.EncryptionAlgorithm.Value); #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Verbose, 0, "Create encrypted message (still empty) [EncAlgo={0} ({1})]", EteeActiveConfig.Seal.EncryptionAlgorithm.FriendlyName, EteeActiveConfig.Seal.EncryptionAlgorithm.Value); #else logger.LogDebug("Create encrypted message (still empty) [EncAlgo={0} ({1})]", EteeActiveConfig.Seal.EncryptionAlgorithm.FriendlyName, EteeActiveConfig.Seal.EncryptionAlgorithm.Value); #endif try { clear.CopyTo(encryptingStream); #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Verbose, 0, "Message encrypted"); #else logger.LogDebug("Message encrypted"); #endif } finally { encryptingStream.Close(); #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Verbose, 0, "Recipient infos added"); #else logger.LogDebug("Recipient infos added"); #endif } }
public Stream Seal(Stream unsealed, SecretKey key, params EncryptionToken[] tokens) { return(Seal(unsealed, key, tokens, null)); }
public Stream Seal(Stream unsealed, SecretKey key, EncryptionToken[] tokens, WebKey[] webKeys) { ITempStreamFactory factory = NewFactory(unsealed); return(Seal(factory, unsealed, key, tokens == null ? null : ConverToX509Certificates(tokens), webKeys)); }
private UnsealResult Unseal(Stream sealedData, SecretKey key, bool streaming) { trace.TraceEvent(TraceEventType.Information, 0, "Unsealing message of {0} bytes for {1} recipient with level {2}", sealedData.Length, key == null ? "known" : "unknown", this.level); UnsealResult result = new UnsealResult(); result.SecurityInformation = new UnsealSecurityInformation(); ITempStreamFactory factory = streaming && sealedData.Length > Settings.Default.InMemorySize ? (ITempStreamFactory) new TempFileStreamFactory() : (ITempStreamFactory) new MemoryStreamFactory(); Stream verified = factory.CreateNew(); using(verified) { result.SecurityInformation.OuterSignature = streaming ? VerifyStreaming(verified, sealedData, null) : VerifyInMem(verified, sealedData, null); verified.Position = 0; //reset the stream Stream decryptedVerified = factory.CreateNew(); using (decryptedVerified) { result.SecurityInformation.Encryption = Decrypt(decryptedVerified, verified, key, result.SecurityInformation.OuterSignature.SigningTime); //always via stream, it works decryptedVerified.Position = 0; //reset the stream result.UnsealedData = factory.CreateNew(); result.SecurityInformation.InnerSignature = streaming ? VerifyStreaming(result.UnsealedData, decryptedVerified, result.SecurityInformation.OuterSignature) : VerifyInMem(result.UnsealedData, decryptedVerified, result.SecurityInformation.OuterSignature); result.UnsealedData.Position = 0; //reset the stream return result; } } }
private SecurityInformation Decrypt(Stream clear, Stream cypher, SecretKey key, DateTime? sealedOn) { int i; bool found; StringBuilder algos; DateTime date = sealedOn == null ? DateTime.UtcNow : sealedOn.Value; trace.TraceEvent(TraceEventType.Information, 0, "Decrypting message for {0} recipient", key == null ? "known" : "unknown"); try { SecurityInformation result = new SecurityInformation(); CmsEnvelopedDataParser cypherData; try { cypherData = new CmsEnvelopedDataParser(cypher); trace.TraceEvent(TraceEventType.Verbose, 0, "Read the cms header"); } catch (Exception e) { trace.TraceEvent(TraceEventType.Error, 0, "The messages isn't encrypted"); throw new InvalidMessageException("The message isn't a triple wrapped message", e); } RecipientInformationStore recipientInfos = cypherData.GetRecipientInfos(); trace.TraceEvent(TraceEventType.Verbose, 0, "Got the recipient info of the encrypted message"); i = 0; found = false; algos = new StringBuilder(); string encryptionAlgOid = cypherData.EncryptionAlgOid; while (!found && i < EteeActiveConfig.Unseal.EncryptionAlgorithms.Count) { Oid algo = EteeActiveConfig.Unseal.EncryptionAlgorithms[i++]; algos.Append(algo.Value + " (" + algo.FriendlyName + ") "); found = algo.Value == encryptionAlgOid; } if (!found) { result.securityViolations.Add(SecurityViolation.NotAllowedEncryptionAlgorithm); trace.TraceEvent(TraceEventType.Warning, 0, "The encryption algorithm {0} isn't allowed, only {1} are", encryptionAlgOid, algos); } trace.TraceEvent(TraceEventType.Verbose, 0, "The encryption algorithm is verified: {0}", encryptionAlgOid); //Key size of the message should not be checked, size is determined by the algorithm //Get recipient, should be receiver. RecipientInformation recipientInfo; ICipherParameters recipientKey; if (key == null) { if (encCertStore != null) { //Find find a matching receiver ICollection recipients = recipientInfos.GetRecipients(); //recipients in the message IList<KeyValuePair<RecipientInformation, IList>> allMatches = new List<KeyValuePair<RecipientInformation, IList>>(); foreach (RecipientInformation recipient in recipients) { trace.TraceEvent(TraceEventType.Verbose, 0, "The message is addressed to {0} ({1})", recipient.RecipientID.SerialNumber, recipient.RecipientID.Issuer); if (recipient is KeyTransRecipientInformation) { IList matches = (IList) encCertStore.GetMatches(recipient.RecipientID); if (matches.Count > 0) { allMatches.Add(new KeyValuePair<RecipientInformation, IList>(recipient, matches)); } } } //Did we find a receiver? if (allMatches.Count == 0) { trace.TraceEvent(TraceEventType.Error, 0, "The recipients doe not contain any of your your encryption certificates"); throw new InvalidMessageException("The message isn't a message that is addressed to you. Or it is an unaddressed message or it is addressed to somebody else"); } //check with encryption cert matches where valid at creation time IList<KeyValuePair<RecipientInformation, IList>> validMatches = new List<KeyValuePair<RecipientInformation, IList>>(); foreach (KeyValuePair<RecipientInformation, IList> match in allMatches) { IList validCertificate = new List<X509Certificate2>(); foreach (X509Certificate2 cert in match.Value) { //Validate the description cert, providing minimal info to force minimal validation. CertificateSecurityInformation certVerRes = CertVerifier.VerifyEnc(DotNetUtilities.FromX509Certificate(cert), null, date, null, false); trace.TraceEvent(TraceEventType.Verbose, 0, "Validated potential decryption certificate ({0}) : Validation Status = {1}, Trust Status = {2}", cert.Subject, certVerRes.ValidationStatus, certVerRes.TrustStatus); if (certVerRes.SecurityViolations.Count == 0) { validCertificate.Add(cert); } } if (validCertificate.Count > 0) { validMatches.Add(new KeyValuePair<RecipientInformation, IList>(match.Key, validCertificate)); } } //If we have a valid encCert use that one, otherwise use an invalid one (at least we can read it, but should not use it) X509Certificate2 selectedCert; if (validMatches.Count > 0) { selectedCert = (X509Certificate2)validMatches[0].Value[0]; recipientInfo = validMatches[0].Key; trace.TraceEvent(TraceEventType.Information, 0, "Found valid decryption certificate ({0}) that matches one the the recipients", selectedCert.Subject); } else { selectedCert = (X509Certificate2)allMatches[0].Value[0]; recipientInfo = allMatches[0].Key; trace.TraceEvent(TraceEventType.Warning, 0, "Found *invalid* decryption certificate ({0}) that matches one the the recipients", selectedCert.Subject); } recipientKey = DotNetUtilities.GetKeyPair(selectedCert.PrivateKey).Private; //we validate the selected certificate again to inform the caller result.Subject = CertVerifier.VerifyEnc(DotNetUtilities.FromX509Certificate(selectedCert), null, date, null, false); } else { trace.TraceEvent(TraceEventType.Error, 0, "The unsealer does not have an decryption certificate and no symmetric key was provided"); throw new InvalidOperationException("There should be an receiver (=yourself) and/or a key provided"); } } else { trace.TraceEvent(TraceEventType.Verbose, 0, "Found symmetric key: {0}", key.IdString); RecipientID recipientId = new RecipientID(); recipientId.KeyIdentifier = key.Id; recipientInfo = recipientInfos.GetFirstRecipient(recipientId); if (recipientInfo == null) { trace.TraceEvent(TraceEventType.Error, 0, "The symmetric key was not found in this cms message"); throw new InvalidMessageException("The key isn't for this unaddressed message"); } trace.TraceEvent(TraceEventType.Verbose, 0, "Found symmetric key in recipients of the cms message"); //Get receivers key recipientKey = key.BCKey; //Validate the unaddressed key if ((((KeyParameter)recipientKey).GetKey().Length * 8) < EteeActiveConfig.Unseal.MinimumEncryptionKeySize.SymmetricRecipientKey) { result.securityViolations.Add(SecurityViolation.NotAllowedEncryptionKeySize); trace.TraceEvent(TraceEventType.Warning, 0, "The symmetric key was only {0} bits while it should be at least {0}", ((KeyParameter)recipientKey).GetKey().Length * 8, EteeActiveConfig.Unseal.MinimumEncryptionKeySize.SymmetricRecipientKey); } } //check if key encryption algorithm is allowed i = 0; found = false; algos = new StringBuilder(); while (!found && i < EteeActiveConfig.Unseal.KeyEncryptionAlgorithms.Count) { Oid algo = EteeActiveConfig.Unseal.KeyEncryptionAlgorithms[i++]; algos.Append(algo.Value + " (" + algo.FriendlyName + ") "); found = algo.Value == recipientInfo.KeyEncryptionAlgOid; } if (!found) { result.securityViolations.Add(SecurityViolation.NotAllowedKeyEncryptionAlgorithm); trace.TraceEvent(TraceEventType.Warning, 0, "Encryption algorithm is {0} while it should be one of the following {1}", recipientInfo.KeyEncryptionAlgOid, algos); } trace.TraceEvent(TraceEventType.Verbose, 0, "Finished verifying the encryption algorithm: {0}", recipientInfo.KeyEncryptionAlgOid); //Decrypt! CmsTypedStream clearStream = recipientInfo.GetContentStream(recipientKey); trace.TraceEvent(TraceEventType.Verbose, 0, "Accessed the encrypted content"); try { clearStream.ContentStream.CopyTo(clear); trace.TraceEvent(TraceEventType.Verbose, 0, "Decrypted the content"); } finally { clearStream.ContentStream.Close(); } return result; } catch (CmsException cmse) { trace.TraceEvent(TraceEventType.Error, 0, "The message isn't a CMS message"); throw new InvalidMessageException("The message isn't a triple wrapped message", cmse); } }
public UnsealResult Unseal(Stream sealedData, SecretKey key) { if (sealedData == null) throw new ArgumentNullException("sealedData"); if (key == null) throw new ArgumentNullException("key"); try { return Unseal(sealedData, key, true); } catch (NotSupportedException) { //Start over, in memory sealedData.Position = 0; return Unseal(sealedData, key, false); } }
private void NonAddressed(IDataSealer sealer, IDataUnsealer unsealer) { String str = "This is a secret message from Alice"; SecretKey key = new SecretKey("btSefztkXjZmlZyHQIumLA==", "aaUnRynIwd3GFQmhXfW+VQ=="); Stream output = sealer.Seal(new MemoryStream(Encoding.UTF8.GetBytes(str)), key); UnsealResult result = unsealer.Unseal(output, key); Console.WriteLine(result.SecurityInformation.ToString()); output.Close(); MemoryStream stream = new MemoryStream(); Utils.Copy(result.UnsealedData, stream); //Assert.IsInstanceOfType(result.UnsealedData, typeof(WindowsTempFileStream)); Assert.AreEqual(ValidationStatus.Valid, result.SecurityInformation.ValidationStatus); Assert.AreEqual(ETEE::Status.TrustStatus.Unsure, result.SecurityInformation.TrustStatus); Assert.AreEqual(alice["Authentication"].Thumbprint, result.AuthenticationCertificate.Thumbprint); Assert.AreEqual(alice["Authentication"].Thumbprint, result.SigningCertificate.Thumbprint); Assert.IsNull(result.SecurityInformation.Encryption.Subject); Assert.AreEqual(str, Encoding.UTF8.GetString(stream.ToArray())); Assert.IsNotNull(result.SecurityInformation.ToString()); }
private void Mixed(IDataSealer sealer, IDataUnsealer unsealer) { String str = "This is a secret message from Alice to everybody"; SecretKey key = new SecretKey("btSefztkXjZmlZyHQIumLA==", "aaUnRynIwd3GFQmhXfW+VQ=="); EncryptionToken receiver1 = new EncryptionToken(Utils.ReadFully("../../bob/bobs_public_key.etk")); Stream output = sealer.Seal(new MemoryStream(Encoding.UTF8.GetBytes(str)), key, receiver1); UnsealResult result = unsealer.Unseal(output, key); Console.WriteLine(result.SecurityInformation.ToString()); MemoryStream stream = new MemoryStream(); Utils.Copy(result.UnsealedData, stream); Assert.AreEqual(ValidationStatus.Valid, result.SecurityInformation.ValidationStatus); Assert.AreEqual(ETEE::Status.TrustStatus.Unsure, result.SecurityInformation.TrustStatus); Assert.AreEqual(alice["Authentication"].Thumbprint, result.AuthenticationCertificate.Thumbprint); Assert.AreEqual(alice["Authentication"].Thumbprint, result.SigningCertificate.Thumbprint); Assert.IsNull(result.SecurityInformation.Encryption.Subject); Assert.AreEqual(str, Encoding.UTF8.GetString(stream.ToArray())); Assert.IsNotNull(result.SecurityInformation.ToString()); output.Position = 0; result = unsealer.Unseal(output); Console.WriteLine(result.SecurityInformation.ToString()); stream = new MemoryStream(); Utils.Copy(result.UnsealedData, stream); Assert.AreEqual(ValidationStatus.Valid, result.SecurityInformation.ValidationStatus); Assert.AreEqual(ETEE::Status.TrustStatus.Unsure, result.SecurityInformation.TrustStatus); Assert.AreEqual(alice["Authentication"].Thumbprint, result.AuthenticationCertificate.Thumbprint); Assert.AreEqual(alice["Authentication"].Thumbprint, result.SigningCertificate.Thumbprint); Assert.AreEqual(bob["825373489"].Thumbprint, result.SecurityInformation.Encryption.Subject.Certificate.Thumbprint); Assert.AreEqual(str, Encoding.UTF8.GetString(stream.ToArray())); Assert.IsNotNull(result.SecurityInformation.ToString()); }